2013-03-27 3 views
3

Я бы хотел вернуть две коллекции в тегах «теги» запроса и «элементы», где каждый тег может содержать 0 ... много элементов. Похоже, если я использую проекцию, он будет считать, что одна коллекция с двумя столбцами, а не с двумя коллекциями, это правильно? Есть ли лучший способ запустить этот поисковый запрос?Как я могу вернуть две коллекции с запросом cypher в neo4j .net-клиенте

Я получаю "the query response contains columns Tags, Items however ...anonymous type does not contain settable properties to receive this data"

var query = client 
    .Cypher 
    .StartWithNodeIndexLookup("tags", "tags_fulltext", keyword) 
    .Match("tags<-[:TaggedWith]-items") 
    .Return((items, tags) => new 
    { 
     Tags = tags.As<Tag>(), 
     Items = items.As<Item>() 
    }); 

var results = await query.ResultsAsync; 

return new SearchResult 
{ 
    Items = results.Select(x => x.Items).ToList(), 
    Tags = results.Select(x => x.Tags).Distinct().ToList() 
}; 

ответ

3

Вариант 1

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

Прежде всего, эта линия:

.StartWithNodeIndexLookup("tags", "tags_fulltext", keyword) 

Должно быть:

.StartWithNodeIndexLookup("tag", "tags_fulltext", keyword) 

То есть, личность должна быть tag не tags. Это связано с тем, что предложение START приводит к набору узлов, каждый из которых представляет собой tag, а не набор узлов, называемый tags. Семантика, но на следующем этапе это упростит ситуацию.

Теперь, когда мы называем это tag вместо tags, мы обновляем нашу MATCH статью в:

.Match("tag<-[:TaggedWith]-item") 

Это говорит «для каждого тега в наборе, пойти и найти каждый элемент, прикрепленный к нему». Опять же, «элемент» является единственным.

Теперь давайте вернуть его:

.Return((tag, item) => new 
{ 
    Tag = tag.As<Tag>(), 
    Items = item.CollectAs<Item>() 
}); 

Здесь мы берем каждый пункт «» и собирать их в набор «предметов». Мое использование особых и множественных чисел в этом коде очень специфично.

В результате Cypher таблица выглядит примерно так:

------------------------- 
| tag  | items  | 
------------------------- 
| red  | A, B, C | 
| blue  | B, D  | 
| green | E, F, G | 
------------------------- 

Окончательная код:

var query = client 
    .Cypher 
    .StartWithNodeIndexLookup("tag", "tags_fulltext", keyword) 
    .Match("tag<-[:TaggedWith]-item") 
    .Return((tag, item) => new 
    { 
     Tag = tag.As<Tag>(), 
     Items = item.CollectAs<Item>() 
    }); 

Это не то, что вписывается в ваш SearchResult хотя.

Вариант 2

Сценарий: Вы хотите получить все теги, которые соответствуют ключевым словам, то все элементы, которые соответствуют любой из этих тегов, но вы не заботитесь о связывании двух вместе ,

Давайте вернемся к Cypher запроса:

START tag=node:tags_fulltext('keyword') 
MATCH tag<-[:TaggedWith]-item 
RETURN tag, item 

Это будет производить Cypher таблицы результатов, как это:

-------------------- 
| tag  | item | 
-------------------- 
| red  | A  | 
| red  | B  | 
| red  | C  | 
| blue  | B  | 
| blue  | D  | 
| green | E  | 
| green | F  | 
| green | G  | 
-------------------- 

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

Мы можем использовать collect сделать:

START tag=node:tags_fulltext('keyword') 
MATCH tag<-[:TaggedWith]-item 
RETURN collect(tag) AS Tags, collect(item) AS Items 

----------------------------------------------------------------------------- 
| tags           | items     | 
----------------------------------------------------------------------------- 
| red, red, red, blue, blue, green, green, green | A, B, C, B, D, E, F, G | 
----------------------------------------------------------------------------- 

Мы не хотим, чтобы все эти дубликаты, хотя, так что давайте просто собирать отдельные из них:

START tag=node:tags_fulltext('keyword') 
MATCH tag<-[:TaggedWith]-item 
RETURN collect(distinct tag) AS Tags, collect(distinct item) AS Items 

-------------------------------------------- 
| tags    | items    | 
-------------------------------------------- 
| red, blue, green | A, B, C, D, E, F, G | 
-------------------------------------------- 

с Cypher работы, превращение его в .NET - это простой перевод:

var query = client 
    .Cypher 
    .StartWithNodeIndexLookup("tag", "tags_fulltext", keyword) 
    .Match("tag<-[:TaggedWith]-item") 
    .Return((tag, item) => new 
    { 
     Tags = tag.CollectDistinct<Tag>(), 
     Items = item.CollectDistinct<Item>() 
    }); 

Резюме

  1. Всегда начинайте с Cypher
  2. Всегда начинайте с Cypher
  3. Когда вы работать Cypher, реализация .NET должна быть почти один-на-один

Проблемы?

Я набрал весь этот код в текстовом поле без поддержки VS, и я не тестировал его. Если что-то сработает, сообщите полный текст и запрос на исключение на нашей странице проблем. Отслеживание сбоев здесь сложно. Отслеживание сбоев без текст исключения, сообщение, трассировка стека и т. Д. Просто поглощает мое время, затрудняя отладку и уменьшая количество времени, которое я могу потратить, помогая вам в противном случае.

+0

Спасибо за тщательную запись. Еще один поворот: используя параметр 2, как мне вернуть набор тегов, которые не имеют каких-либо тегов с отношениями с элементами? Это теги, только если они соответствуют поиску индекса, и у них нет элементов. Коллекция элементов все равно будет возвращать элементы, теги которых соответствуют индексу. – MonkeyBonkey

+0

http://docs.neo4j.org/chunked/stable/query-match.html#match-optional-typed-and-named-relationship –

+0

Впечатляющий ответ, @TathamOddie! –

 Смежные вопросы

  • Нет связанных вопросов^_^