Neo4j: Как получить взаимные узлы для списка узлов

#neo4j #cypher

Вопрос:

У меня есть этот зашифрованный код:

 MATCH path = (me:Person {uuid: '{my_id}'})-[:friendship*2]->(p:Person)-[:courses]->(c:Course)
WHERE p.uuid<>'{my_id}'
RETURN distinct(c) as courses
 

Этот код возвращает все курсы каждого человека в отношениях *2. Но как я могу получить только аналогичные курсы для этих Людей?

Пример фокса: Человек1 имеет: Курс1, Курс2, Курс3.

Человек2 имеет: Курс2, Курс3, Курс4

Мой код вернется [Course1, Course2, Course3, Course4] , но мне нужно [Course2, Course3] (только взаимное)

Спасибо за ответы.

Обновление 1: Вот моя версия:

 MATCH (me:Person {uuid: '{my_id}'})-[:friendship*2]->(p:Person)-[cr:courses]->(c:Course)
WITH collect(p) as persons, collect(cr) as courses_rel, g, collect(c) as courses
WHERE p.uuid<>'{my_id}' and all(rel in courses_rel WHERE all(person in persons WHERE startNode(rel) = person ))
RETURN courses
 

этот код работает, но возвращает неправильные данные без фильтрации

Обновление 2: Вот sccreenshot

Мне нужно пройти 3 курса: Ackerman, 27 Pines Golf Course, 18 Mile Creek Golf

Комментарии:

1. Таким образом, он не должен ничего возвращать в случае, если среди всех отношений *r нет общих курсов?

2. да, мне нужны только общие курсы

Ответ №1:

Во-первых, найдите всех отдельных людей на уровне 2 и все отдельные курсы, которые у них есть. Передайте эти значения в следующую часть запроса с помощью WITH .

Затем для каждого из этих курсов проверьте, есть ли all у людей это или нет.

 MATCH path = (me:Person {uuid: '{my_id}'})-[:friendship*2]->(p:Person)-[:courses]->(c:Course)
WHERE p.uuid<>'{my_id}'
WITH collect(distinct(c)) as courses, collect(distinct(p)) as persons
MATCH (c:Course)
WHERE c in courses and all(p in persons where (p)-[:courses]->(c))
RETURN c as courses
 

ИЗМЕНИТЬ:
В случае, если вам нужны курсы, которые были добавлены по крайней мере двумя друзьями, затем найдите количество человек для каждого курса и отфильтруйте их.

 MATCH path = (me:Person {uuid: '{my_id}'})-[:friendship*2]->(p:Person)-[:courses]->(c:Course)
WHERE p.uuid<>'{my_id}'
WITH course, collect(distinct(p)) as persons
WHERE size(persons) >= 2
RETURN collect(course) as courses
 

Комментарии:

1. Большое спасибо!!, это работает) Мой код был похож, но он не работал 🙁 .

2. К сожалению, этот код для меня тоже не работает. Если у меня есть два друга, и у них есть 2 общих клубы, тогда это работает, но если у меня есть вторая пара друзей: 3 и 4 друг друга, и у них совершенно разные клубы, в общем, тогда этот код будет возвращать пустой список, потому что WHERE c in courses and all(p in persons where (p)-[:courses]->(c)) код будет возвращать только те курсы, в которых каждый друг, а мне как раз нужен клубы, которые были добавлены, по меньшей мере, двух друзей. Есть какие-нибудь идеи?

3. Раджендра Кадам, я добавил скриншот

4. Я думал, что это распространено среди всех друзей

5. Обновлен ответ

Ответ №2:

Тогда вам также нужно будет соответствовать вашим курсам. Вы можете повторно использовать одну и ту же переменную, чтобы получить только общие курсы:

 MATCH (c:Course)<-[:courses]-(me:Person {uuid: '{my_id}'})-[:friendship*2]->(p:Person)-[:courses]->(c)
WHERE p.uuid<>'{my_id}'
RETURN distinct(c) as courses