Вернуть node если отношения нет
Я пытаюсь создать запрос с использованием cypher, который будет "обнаруживать" недостающие компоненты, которые может иметь шеф-повар. Мой график настроен так:
(ingredient_value)-[:is_part_of]->(ingredient)
(ingredient)
будет иметь ключ/значение name= "цветов красителя". (ingredient_value)
может иметь ключ/значение значения = "красный" и "является частью" (ingredient, name="dye colors")
.
(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)
Я использую этот запрос, чтобы получить все ingredients
, но не их фактические значения, которые требуется для рецепта, но я бы хотел, чтобы возвращал только ingredients
, который у шеф-повара нет, вместо всех ингредиенты, необходимые для каждого рецепта. Я попробовал
(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)<-[:has_ingredient*0..0]-chef
но это ничего не вернуло.
Является ли это чем-то, что может быть выполнено cypher/neo4j, или это то, что лучше всего обрабатывать, возвращая все ингредиенты и самостоятельно сортируя их?
Бонус: Также есть способ использовать cypher для соответствия всем значениям, которые повар имеет для всех значений, которые требуется рецепту. Пока что я вернул все частичные совпадения, возвращаемые chef-[:has_value]->ingredient_value<-[:requires_value]-recipe
и агрегируя результаты самостоятельно.
Ответы
Ответ 1
Обновление 01/10/2013:
Переместился через ссылку Neo4j 2.0:
Старайтесь не использовать дополнительные отношения.
Прежде всего,
не использовать их следующим образом:
MATCH a-[r?:LOVES]->() WHERE r IS NULL
, где вы просто убедитесь, что они не существуют.
Вместо этого сделайте следующее:
MATCH a WHERE NOT (a)-[:LOVES]->()
Использование cypher для проверки того, не существует ли отношения:
...
MATCH source-[r?:someType]-target
WHERE r is null
RETURN source
Что? mark делает связь необязательной.
ИЛИ
В neo4j 2 do:
...
OPTIONAL MATCH source-[r:someType]-target
WHERE r is null
RETURN source
Теперь вы можете проверить наличие несуществующих (нулевых) отношений.
Ответ 2
Для выборки узлов, не имеющих отношения
Это хороший вариант проверки отношения существует или нет
MATCH (player)-[r:played]->()
WHERE r IS NULL
RETURN player
Вы также можете проверить несколько условий для этого
Он вернет все узлы, которые не имеют "сыгранных" или "незаложенных" отношений.
MATCH (player)
WHERE NOT (player)-[:played|notPlayed]->()
RETURN player
Получить узлы, которые не имеют никакой реальности
MATCH (player)
WHERE NOT (player)-[r]-()
RETURN player
Он проверит node отсутствие входящих/исходящих отношений.
Ответ 3
Если вам нужна семантика условного исключения, вы можете достичь этого таким образом.
Как и в случае с neo4j 2.2.1, вы можете использовать предложение OPTIONAL MATCH
и фильтровать непревзойденные (NULL
) узлы.
Также важно использовать предложение WITH
между предложениями OPTIONAL MATCH
и WHERE
, так что WHERE
ведет себя как фильтр, а не как часть шаблона соответствия.
Предполагая, что у нас есть 2 типа узлов: Person
и Communication
. Если я хочу получить все Лица, которые никогда не общались по телефону, но, возможно, обменивались другими способами, я бы сделал этот запрос:
MATCH (p: Person)
OPTIONAL MATCH p--(c: Communication)
WHERE c.way = 'telephone'
WITH p, c
WHERE c IS NULL
RETURN p
Обратите внимание, что первое предложение WHERE
ведет себя точно так же, как часть соответствия.
Литература:
http://neo4j.com/docs/stable/query-optional-match.html#_introduction_3
http://java.dzone.com/articles/new-neo4j-optional
Ответ 4
Я выполнил эту задачу, используя гремлин. Я сделал
x=[]
g.idx('Chef')[[name:'chef1']].as('chef')
.out('has_ingredient').as('alreadyHas').aggregate(x).back('chef')
.out('has_value').as('values')
.in('requires_value').as('recipes')
.out('requires_ingredient').as('ingredients').except(x).path()
Это вернуло пути всех недостающих ингредиентов. Я не смог сформулировать это на языке cypher, по крайней мере, для версии 1.7.
Ответ 5
Я написал суть, показывающую, как это можно сделать вполне естественно, используя Cypher 2.0
http://gist.neo4j.org/?9171581
Ключевым моментом является использование опционального соответствия доступным ингредиентам, а затем сравнение с фильтрами для отсутствующих (нулевых) ингредиентов или ингредиентов с неправильным значением.
Обратите внимание, что понятие является декларативным и не нуждается в описании алгоритма, вы просто записываете, что вам нужно.
Ответ 6
Последний запрос должен быть:
START chef = node(..)
MATCH (chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)
WHERE (ingredient)<-[:has_ingredient]-chef
RETURN ingredient
Этот шаблон: (ingredient)<-[:has_ingredient*0..0]-chef
Является ли причина, по которой она ничего не вернула. *0..0
означает, что длина отношений должна быть равна нулю, а это означает, что ингредиент и шеф-повар должны быть одинаковыми node, которых они не являются.