0
votes

I'm looking to perform a set operation in a Neo4j cypher. Basically I have relationships to a set of nodes from two directions, I want to find only nodes on one side which have a relationship to all those on the other.

Given a graph similar to the following:

  /----- b1 -\
 /            \
a ------ b2 --c1
 \          \/
  \         /\
   \---- b3 --c2     

I would only like c1 to be returned, as c2 does have a direct relationship with b1 while a does.

2

2 Answers

0
votes

I have a solution which seems to work, but I don't know if it's optimal.

match (a:A)--(b:B) 
with a, count(b) as bCount1
    match (a)--(b:B)--(c:C)
with c, bCount1, count(b) AS bCount2
where bCount1 = bCount2
return c
0
votes

You could possibly use a label to denote nodes as being in one set or the other (am assuming they're mutually exclusive). I'm also assuming that the node "a" is a root node and/or doesn't need to be directly connected to "c1" or "c2".

In your above ASCII art example, assuming "b1" has a label of "Set1" and all others have "Set2", something like this might work:

MATCH (n:Set2)--(o:Set1), (allS1:Set1)
WHERE length(collect(o)) = count(allS1)
WITH n, length(collect(o))
RETURN n

...or a variation thereof. Again, this is assuming that you're doing this one set at a time. Doing both shouldn't take too much more effort. It also may not be the most efficient, but it should do the trick. Give it a shot and let us know.

HTH, and as always, if there's a better way to do this (as there very well might be), let's see those answers!