Повернути вузол, якщо відносини немає


88

Я намагаюся створити запит за допомогою cypher, який буде "знаходити" відсутні компоненти, які може бути у шеф-кухаря. Мій графік налаштований так:

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

(ingredient)мав би ключ / значення name = "кольори барвника". (ingredient_value)може мати ключ / значення 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, щоб відповідати всім значенням, які має кухар, до всіх значень, які вимагає рецепт. Поки що я повернув лише всі часткові збіги, які повертає a, chef-[:has_value]->ingredient_value<-[:requires_value]-recipeі сам збираю результати.


Перевірте тут інформацію, що стосується v3: stackoverflow.com/questions/25673223/…
Maciej,

Для майбутніх користувачів; можна використовувати existsв WHEREреченні (також його також заперечувати), neo4j.com/developer/subqueries/#existential-subqueries для отримання додаткової інформації.
ozanmuyes

Відповіді:


157

Оновлення 10.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

? позначка робить відносини необов’язковими.

АБО

У neo4j 2 виконайте:

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

Тепер ви можете перевірити неіснуючі (нульові) відносини.


3
У Neo4j 2.0 використовуйте OPTIONAL MATCH для відповідності необов’язкових відносин, тобто перший приклад буде виглядати як OPTIONAL MATCH (джерело) - [r: someType] - (target) RETURN джерело, r
boggle

Я намагаюся мати позначений вузол у WHERE NOT, це не працює. Подібно: ВІДПОВІДАЙТЕ ДЕ, де НЕ (а) - [: ЛЮБИТЬ] -> (Незнайомець), у цьому "Незнайомці" мітка вузла. Я використовую neo4j версії 2.1.2
Крішна Шетті

1
Неважливо, я розумію, чому ви хочете показати прогресію, щоб дійти до цієї відповіді: ЗМІСТИТЕ ДЕ, А НЕ (а) - [: ЛЮБИТЬ] -> ()
NumenorForLife

4
MATCH a...Приклад повинен тепер бутиMATCH (a) WHERE NOT (a)-[:LOVES]->()
Лі

1
@ gil-stal Чому я не можу використовувати ім'я вузла з цим запитом, як це. НАЙДІТЬ ДЕ, де НЕ (a) - [: ЛЮБИТЬ] -> (b: SomeLabel). Якщо я не використовую ім'я вузла, це працює.
iit2011081,

15

Для отримання вузлів без будь-яких відносин

Це хороший варіант перевірити, чи існують стосунки чи ні

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

Ви також можете перевірити кілька умов для цього. Це поверне всі вузли, які не мають "відтворених" або "не відтворених" відносин.

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

Вибирати вузли, які не мають жодної реальності

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

Він перевірить вузол, який не має ніяких вхідних / вихідних відносин.


4
MATCH (player) WHERE NOT (player)-[r]-() RETURN player дає змінну r не визначена помилка. Як я можу визначити r?
Chathura Wijeweera

щоб виправити це, або вкажіть стосунки (наприклад (player -[:rel]- ()), або залиште порожніми для будь-яких стосунків(player -[]- ()
Archemar

MATCH (player) WHERE NOT (player)-[]-() RETURN player- Це чудово працює
Прашант Терала,

Ваш перший запит насправді помилковий. Сам шаблон MATCH завжди повертає лише існуючі відносини, причому жоден з них не має значення NULL. Отже, у вашому рядку WHERE немає з чого фільтрувати.
Крісті С.

@CristiS. Дякую що дали мені знати. Я оновив запит, який повинен працювати
Сатіш Шінде,

8

Якщо вам потрібна семантична умовна виключення, ви можете досягти цього таким чином.

Починаючи з neo4j 2.2.1, ви можете використовувати OPTIONAL MATCHпропозицію та відфільтрувати NULLвузли unmatched ( ).

Також важливо використовувати 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

Я написав суть, показуючи, як це можна зробити цілком природно за допомогою Cypher 2.0

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

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

Зверніть увагу, що поняття є декларативним і не потребує опису алгоритму, ви просто записуєте те, що вам потрібно.


2

Я виконав це завдання за допомогою gremlin. я зробив

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.


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


Так, але це не повертає бажаного інгредієнта. Це повертає те, що шеф-кухар вже має спільного з рецептом, я хочу з’ясувати різницю.
Микола
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.