Вопрос по neo4j, cypher – Вернуть узел, если связь отсутствует

66

Я пытаюсь создать запрос с использованием шифра, который будет "Найти" Отсутствующие ингредиенты, которые может иметь шеф-повар, Мой график настроен так:

(ingredient_value)-[:is_part_of]->(ingredient)

(ingredient) будет иметь ключ / значение name = & quot; dye colors & quot ;.(ingredient_value) может иметь ключ / значение value = & quot; красный & quot; и "является частью"(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, или это лучше всего обрабатывать, возвращая все ингредиенты и сортируя их сам?

Бонус: также есть способ использовать шифр, чтобы сопоставить все значения, которые имеет шеф-повар, со всеми значениями, которые требует рецепт. До сих пор я возвращал только все частичные совпадения, которые были возвращеныchef-[:has_value]->ingredient_value<-[:requires_value]-recipe и агрегирование результатов сам.

Проверьте здесь для информации, относящейся к v3:stackoverflow.com/questions/25673223/… Maciej

Ваш Ответ

6   ответов
7

условно исключить & quot; семантически, вы можете достичь этого таким образом.

Начиная с neo4j 2.2.1, вы можете использоватьOPTIONAL MATCH пункт и отфильтровать непревзойденный (NULL) узлы.

Также важно использоватьWITH пункт междуOPTIONAL MATCH а такжеWHERE пункты, так что первый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

Шаблон совпадения будет сопоставлять всех людей с их сообщениями, гдеc будетNULL для не телефонной связи. Тогда фильтр (WHERE послеWITH) отфильтрует телефонную связь оставив все остальные.

Рекомендации:

http://neo4j.com/docs/stable/query-optional-match.html#_introduction_3 http://java.dzone.com/articles/new-neo4j-optional

2

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 означает, что длина отношений должна быть нулевой, что означает, что ингредиент и шеф-повар должны быть одним и тем же узлом, которым они не являются.

Да, но это не возвращает желаемый ингредиент. Он возвращает то, что шеф-повар уже имеет общего с рецептом, я хочу выяснить разницу. Nicholas
2

показывающую, как это можно сделать вполне естественно, используя Cypher 2.0

http://gist.neo4j.org/?9171581

Ключевым моментом является использование необязательного соответствия с доступными ингредиентами, а затем сравнение с фильтром для отсутствующих (нулевых) ингредиентов или ингредиентов с неправильным значением.

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

12

Это хороший вариант, чтобы проверить, существуют отношения или нет

MATCH (player)-[r:played]->()
    WHERE r IS NULL 
    RETURN player

Вы также можете проверить несколько условий для этого Он вернет все узлы, которые не "играли" Или & quot; notPlayed & quot; Отношения.

MATCH (player) 
 WHERE NOT (player)-[:played|notPlayed]->()
 RETURN player

Извлекать узлы, не имеющие отношения

MATCH (player) 
WHERE NOT (player)-[r]-()
RETURN player

Он проверит узел, не имеющий никаких входящих / исходящих отношений.

MATCH (player) WHERE NOT (player)-[r]-() RETURN player  даетVariable r not defined ошибка. Как я могу определить г?
2

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()

Это вернуло пути всех недостающих ингредиентов. Я не смог сформулировать это на шифровальном языке, по крайней мере, для версии 1.7.

127

Update 01/10/2013:

Наткнулся на это в Neo4j2.0 ссылка:

Try not to use optional relationships. Above all,

don’t use them like this:

MATCH a-[r?:LOVES]->() WHERE r IS NULL where you just make sure that they don’t exist.

Instead do this like so:

MATCH a WHERE NOT (a)-[:LOVES]->()

Использование cypher для проверки, если отношения не существуют:

...
MATCH source-[r?:someType]-target
WHERE r is null
RETURN source

? знак делает отношения необязательными.

ИЛИ ЖЕ

В neo4j 2 делаем:

...
OPTIONAL MATCH source-[r:someType]-target
WHERE r is null
RETURN source

Теперь вы можете проверить наличие несуществующих (нулевых) отношений.

В Neo4j 2.0 используйте OPTIONAL MATCH для соответствия необязательным отношениям, т.е. первый пример будет выглядеть как OPTIONAL MATCH (source) - [r: someType] - (target) RETURN source, r
Не могли бы вы изменить этот ответ, чтобы отразить обновление?
Я пытаюсь иметь помеченный узел в WHERE NOT, он не работает. Например: сопоставить, где нет (a) - [: LOVES] - & gt; (Незнакомец), в этом «Незнакомец»; это метка узла. Я использую neo4j версии 2.1.2
MATCH a... пример теперь должен бытьMATCH (a) WHERE NOT (a)-[:LOVES]->()
Неважно, я понимаю, почему вы хотите показать прогресс в достижении этого ответа: СОГЛАСИТЕСЬ ГДЕ НЕ (a) - [: LOVES] - & gt; ()

Похожие вопросы