RavenDB начинается с Linq (материализованный путь) - PullRequest
4 голосов
/ 30 марта 2012

Этот запрос не выполняется (RavenDB 1.0.701)

var items= RavenSession.Query<Item>().Where(x => "161 193".StartsWith(x.MaterializedPath)).ToList();

Есть ли другой способ?

Прежде чем вы спросите, я пытаюсь найти у родителей (предков) данные с древовидной структурой с материализованным путем (столбец линии) .

Ответы [ 2 ]

2 голосов
/ 30 марта 2012

Вы не можете сделать это в RavenDB - запрашиваемое поле должно быть слева от предиката, а справа от предиката не может ссылаться на другое поле.

Что касается того, как это реструктурировать - Извините, не уверен.

Редактировать:

Хорошо, потребовались некоторые эксперименты - но мне удалось заставить его работать, ЕСЛИ можно либо реструктурировать MaterializedPath, либо добавить новое свойство. Я предполагаю, что это новое свойство, чтобы избежать путаницы.

// Sample class: 
public class Item 
{ 
  public string Name { get;set;}
  public Dictionary<int, string> Path { get;set;} // Zero-based key on path. 
}


// Query: Find nodes with path "A B"  
var query = session.Query<Item>().AsQueryable();
query = query.Where(item => item.Path[0] == "A");
query = query.Where(item => item.Path[1] == "B");

var found = query.ToList();

И вот оно работает:

IDocumentStore store = new EmbeddableDocumentStore { RunInMemory = true };
store.Initialize();

// Install Data
using (var session = store.OpenSession())
{
    session.Store(new Item("Foo1", "A")); // NB: I have a constructor on Item which takes the path and splits it up. See below. 
    session.Store(new Item("Foo2", "A B"));
    session.Store(new Item("Foo3", "A C D"));
    session.Store(new Item("Foo4", "A B C D"));
    session.Store(new Item("Foo5", "C B A"));
    session.SaveChanges();
}

using (var session = store.OpenSession())
{
    var query = session
        .Query<Item>().AsQueryable();

    query = query.Where(item => item.Path[0] == "A");
    query = query.Where(item => item.Path[1] == "B");

    var found = query.ToList();

    Console.WriteLine("Found Items: {0}", found.Count );

    foreach(var item in found)
    {
        Console.WriteLine("Item Name {0}, Path = {1}", item.Name, string.Join(" ", item.Path));
    }
}

Выходные данные:

Found Items: 2
Item Name Foo2, Path = [0, A] [1, B]
Item Name Foo4, Path = [0, A] [1, B] [2, C] [3, D]

Надеюсь, это поможет.

Редактировать 2:

Конструктор для Item выглядит следующим образом, просто для удобства тестирования:

    public Item(string name, string materializedPath)
    {
        Name = name;
        var tmpPath = materializedPath.Split(' ');
        Path =
            tmpPath
                .Zip(Enumerable.Range(0, tmpPath.Count()), (item, index) => new {Item = item, Index = index})
                .ToDictionary(k => k.Index, v => v.Item);
    }
1 голос
/ 30 марта 2012

Я предложу построить индекс, который будет содержать каждую из возможностей поиска.Это создаст множество элементов в вашем индексе, но в то же время Lucene позволяет быстро выполнять поиск

...