Need only common nodes across multiple paths - Neo

2019-09-09 22:55发布

问题:

sMy Cypher query finds the common child nodes for several starting nodes. Each path has only it's node id's extracted and returned resulting in hundreds of rows in each path. See p1 and p2 example (showing only 3 rows and two start points).

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

What I would like is to intersect the paths in cypher during the query so that I don't have to do it after. In php I would iterate using:

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

This would return 9,3 from the above example because they are the only common nodes shared by all paths. Is there a way to do this in Cypher so that I don't have hundreds of rows returned?

Thanks!

回答1:

I believe this will meet your needs.

Here is a picture of the data under consideration.

// 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

EDIT: updated solution to include a third path

// 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