0
votes

I have what feels like a fairly simple Cypher question.

I have the following data, where I have two A nodes and 3 B nodes with b1 being related to a1, b2 related to a2, and b3 is shared and related to both a1 and a2. My goal is write a Cypher statement that, given a particular A node, will return the B nodes that are connected only to it and are not related with any other A node. For example, when given node a1 the query should return b1 and when given node a2, b2 should be returned. The b3 node, which is relate to both a1 and a2, should never be returned from this query regardless of which A node is specified. Said differently, I am trying to find the B nodes that are unique to a given A node, in that the resulting B nodes are not related to any other A node other than the one specified in my match.

This example data will (hopefully) make my goal more clear:

CREATE (n:A { code: 'a1' })
CREATE (n:A { code: 'a2' })
CREATE (n:B { code: 'b1' })
CREATE (n:B { code: 'b2' })
CREATE (n:B { code: 'b3' })

match (a:A), (b:B) where a.code = 'a1' and b.code = 'b1' create (a)<-[r:A_AND_B]-(b) return a, r, b
match (a:A), (b:B) where a.code = 'a2' and b.code = 'b2' create (a)<-[r:A_AND_B]-(b) return a, r, b
match (a:A), (b:B) where a.code = 'a1' and b.code = 'b3' create (a)<-[r:A_AND_B]-(b) return a, r, b
match (a:A), (b:B) where a.code = 'a2' and b.code = 'b3' create (a)<-[r:A_AND_B]-(b) return a, r, b

If I were willing to include the shared b3 node, the query would be straight forward and be:

match (a:A)-[r:A_AND_B]-(b:B) where a.code = 'a1' return b

This returns b1 and b2. However, given that I do want to include any B nodes that are relate to a different A node (b2 should not be returned in this case), I'm struggling to come up with the right approach and syntax.

I've explored explored Cypher's WITH and OPTIONAL MATCH with so far no luck. I am also able to accomplish what I want if I use two separate queries, which is a bit of a cheat and sidesteps the learning opportunity.

Can someone provide a boost?

1

1 Answers

1
votes

How about something like this:

match (a:A)-[:A_AND_B]-(b:B) 
where a.code = 'a1' 
match (b)-[r:A_AND_B]-(:A) 
with b, count(r) as c 
where c = 1 
return b