1
votes

I am trying to build a cypher statement for neo4j where I know 2-n starting nodes by name and need to find a node (if any) that can be reached by all of the starting nodes.

At first I tought it was similar to the "Mutual Friend" situation that could be handled like (start1)-[*..2]->(main)<-[*..2]-(start2) but in my case I often have more then 2 starting points up around 6 that I know by name.

So basically I am puzzled by how i can include the third, fourth and so on node into the cypher to be able to find a commmon root amongst them.

how do I find Anders

In the above Example from the neo4j Website I would need a path starting with 'Dilshad', 'Becky' and 'Cesar' to check if they have a common friend (Anders) excluding 'Filipa' and 'Emil' as they are not friends of all three.

So far I would create a statement programmatically that looks like

MATCH (start1 {name:'Person1'}), (start2 {name:'Person2'}), 
(start3 {name: 'Person3'}), (main) 
WHERE (start1)-[*..2]->(main) AND 
(start2)-[*..2]->(main) AND 
(start3)-[*..2]->(main) RETURN distinct main

But I was wondering if there is a more elegant / efficient way in cypher possibly where I could use the list of names as parameter

1

1 Answers

1
votes

The query shown in your question is building a cartesian product because you are matching multiple disconnected patterns.

Instead of MATCH all nodes separately and use WHERE to restrict the relations between these nodes you can do something like:

MATCH (start1 {name:'Person1'})-[*..2]->(main),
(start2 {name:'Person2'})-[*..2]->(main), 
(start3 {name: 'Person3'})-[*..2]->(main)
RETURN main

The above query will be more efficient because it will match only the required pattern. Note that when you are doing MATCH (start1 {name:'Person1'}), (start2 {name:'Person2'}), (start3 {name: 'Person3'}), (main), the part (main) is matching all nodes of your graph because no restrictions to this are specified. You can use PROFILE with your query to see it more clearly.