Нужны только общие узлы на нескольких путях - Neo4j Cypher

Запрос sMy Cypher находит общие дочерние узлы для нескольких начальных узлов. Для каждого пути извлекается и возвращается только его идентификатор узла, в результате чего в каждом пути появляются сотни строк. См. Пример p1 и p2 (показаны только 3 ряда и две начальные точки).

Match p1=(n1:node{name:"x" })-[r:sub*]->(i)), p2=(n2:node{name:"y" })-[r:sub*]->(i))
RETURN DISTINCT i, extract(a IN nodes(p1)| a.id) as p1, extract(b IN nodes(p2)| b.id) as p2

----RESULTS----

p1=1,4,3
p1=1,8,3
p1=1,8,9,3 

p2=6,7,3
p2=6,5,9,3
p2=6,7,10,3

Я бы хотел пересечь пути в cypher во время запроса, чтобы мне не приходилось делать это после. В php я бы повторил, используя:

$result = array_intersect($p1,$p2);

Это вернет 9,3 из приведенного выше примера, потому что это единственные общие узлы, общие для всех путей. Есть ли способ сделать это в Cypher, чтобы мне не возвращались сотни строк?

Спасибо!


person Damon    schedule 05.02.2016    source источник


Ответы (1)


Я верю, что это удовлетворит ваши потребности.

Вот изображение рассматриваемых данных. введите описание изображения здесь

// match the two different paths with the common ending i
match p1=(n1:Node {name: 1 })-[:SUB*]->(i)
, p2=(n2:Node {name: 6 })-[:SUB*]->(i)

// collect both sets of paths for every 
with i, collect(p1) as p1, collect(p2) as p2

// recombine the nodes of the first path(s) as distinct collections of nodes
unwind p1 as p
unwind nodes(p) as n
with i, p2, collect( distinct n ) as p1

// recombine the nodes of the second path(s) as distinct collections of     
unwind p2 as p
unwind nodes(p) as n
with i, p1, collect( distinct n ) as p2

// return the common ending node with the nodes common to each path
return i, [n in p1 where n in p2 | n.name] as n

РЕДАКТИРОВАТЬ: обновленное решение, чтобы включить третий путь

// match the two different paths with the common ending i
match p1=(n1:Node {name: 1 })-[:SUB*]->(i)
, p2=(n2:Node {name: 6 })-[:SUB*]->(i)
, p3=(n3:Node {name: 4 })-[:SUB*]->(i)

// collect both sets of paths for every 
with i, collect(p1) as p1, collect(p2) as p2, collect(p3) as p3

// recombine the nodes of the first path(s) as distinct collections of nodes
unwind p1 as p
unwind nodes(p) as n
with i, p2, p3, collect( distinct n ) as p1

// recombine the nodes of the second path(s) as distinct collections of     
unwind p2 as p
unwind nodes(p) as n
with i, p1, p3, collect( distinct n ) as p2

// recombine the nodes of the third path(s) as distinct collections of     
unwind p3 as p
unwind nodes(p) as n
with i, p1, p2, collect( distinct n ) as p3

// return the common ending node with the nodes common to each path
return i, [n in p1 where n in p2 and n in p3 | n.name] as n
person Dave Bennett    schedule 06.02.2016
comment
Спасибо, похоже, это сработает. У меня возникли проблемы с изменением линии возврата, чтобы она принимала более двух путей, например. p3 p4 и т. д. Как я могу объединить более двух? Спасибо! - person Damon; 06.02.2016
comment
Я добавил решение с тремя путями. Если у меня будет время, я посмотрю, смогу ли я предложить вам универсальное решение для пути n. - person Dave Bennett; 07.02.2016
comment
Большое спасибо за это, Дэйв - ты так просто делаешь это! - person Damon; 08.02.2016