несколько матчей в Cypher - Neo4j - PullRequest
1 голос
/ 30 января 2020

Документация Neo4j дает следующий пример:

CREATE (adam:User { name: 'Adam' }),(pernilla:User { name: 'Pernilla' }),
(david:User { name: 'David'   }),   (adam)-[:FRIEND]->(pernilla),
(pernilla)-[:FRIEND]->(david)

и

MATCH (user:User { name: 'Adam' })-[r1:FRIEND]-(friend) 
MATCH (friend)-[r2:FRIEND]-(friend_of_a_friend) 
RETURN friend_of_a_friend.name AS fofName

возвращает

+---------+ 
| fofName | 
+---------+ 
| "David" | 
| "Adam"  | 
+---------+ 
2 rows

Я понимаю, почему Дэвид возвращается, но я не Я не понимаю, почему Адам вернулся. Адам не друг друга. Я ценю объяснение.

Ответы [ 3 ]

3 голосов
/ 30 января 2020

Это потому, что у второго MATCH нет направления

MATCH (friend)-[r2:FRIEND]-(friend_of_a_friend) 

Так что у pernilla он соответствует -[:FRIEND]- в обоих направлениях, что, хотя и соответствует Давиду, также возвращает вас к Адаму ,

Если вы добавите направление ко второму MATCH, как показано ниже, оно должно вернуть только Дэвида. Хотя у Перниллы два отношения FRIEND, одно является входящим (от Адама), а другое - исходящим (для Дэвида).

MATCH (user:User { name: 'Adam' })-[r1:FRIEND]-(friend) 
MATCH (friend)-[r2:FRIEND]->(friend_of_a_friend) 
RETURN friend_of_a_friend.name AS fofName
1 голос
/ 30 января 2020

это то, что доказывает, что правильное понимание того, что означает шаблон, необходимо для формирования запросов, которые дают правильные и ожидаемые результаты. Шаблон может быть отдельным узлом, отношением или путем. когда вы сделали это MATCH (user:User { name: 'Adam' })-[r1:FRIEND]-(friend), вы ищете все шаблоны, то есть всех друзей «Адама», и поймете, что отношение не направлено. И он должен быть бесцельным, потому что друг двунаправленный ... и когда вы сделали MATCH (friend)-[r2:FRIEND]-(fof), вы снова ищете друзей друга Адама и без указаний. А «Адам» - друг его друга. Вот почему вы видите «Адам» в результатах. Чтобы быть более понятным здесь, вы не ищете друзей друзей «Адама». Вы ищете всех друзей для любого друга "Адама". Надеюсь, это помогло

, если вы не хотите видеть «Адама», вы можете сделать любое из следующего,

MATCH (user:User { name: 'Adam' })-[r1:FRIEND]-(friend)-[r2:FRIEND]-(fof)
RETURN fof.name```

или это,

MATCH (user:User { name: 'Adam' })-[r1:FRIEND*2]-(fof) RETURN fof.name

i предложил бы пройти эту документацию образцов https://neo4j.com/docs/cypher-manual/current/syntax/patterns/

1 голос
/ 30 января 2020

У вас есть два отдельных совпадения в вашем запросе. Первый находит всех друзей Адама, для которых есть только один: Pernilla.

Второй MATCH находит друзей этого друга (Pernilla), и есть два узла, связанных: отношения FRIEND: Адам (это будет проходить отношения, которые вы изначально использовали, чтобы получить от Адама до Перниллы) и Дэвида.

Если вы вместо этого использовали один МАТЧ для этого:

MATCH (user:User { name: 'Adam' })-[:FRIEND]-(friend)-[:FRIEND]-(friend_of_a_friend)
RETURN friend_of_a_friend.name AS fofName

или

MATCH (user:User { name: 'Adam' })-[:FRIEND]-(friend), (friend)-[:FRIEND]-(friend_of_a_friend)
RETURN friend_of_a_friend.name AS fofName

тогда ты вернешь Дэвида только как друга друга. Причина в том, что уникальность Cypher заключается в том, что для каждого пути в MATCH отношения могут быть пройдены только один раз. Когда есть два МАТЧа, тогда нет никаких ограничений между пройденными между ними отношениями.

Это более подробно проиллюстрировано в документации Cypher по уникальности .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...