cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Retrieve Common Denominator

Ajwah
Node Link

Given a top node A
And given that this top node A can have any arbitrary amount of children. For illustration purposes let these children be c1, c2 and c3
Each of these children in turn point to an arbitrary amount of items with a subset of items that are pointed at by all three children, c1, c2 and c3

Question: How do I retrieve that subset of items that are being pointed at by c1, c2 and c3?

Example:
A has children c1, c2 and c3.

Suppose c1 has the items: i1, i2, i3, i4
Suppose c2 has the items: i1, i5, i6, i4
Suppose c3 has the items: i1, i2, i7, i4

Then the desired subset would be the items: i1 and i4.
i2 is excluded because it is not being pointed at by c2.

Here is an example query that retrieves me the union as opposed to the desired intersection:

MATCH (a: A)-[:HAS_CHILD]->(c: Child)-[HAS_ITEM]->(i: Item)
RETURN i

I tried to remedy this by doing:

MATCH (a: A)-[:HAS_CHILD]->(c: Child)-[HAS_ITEM]->(i: Item)
WITH i, collect(c) as children
WHERE ALL(c in children WHERE((c)-[:HAS_ITEM]->(i)))
RETURN i

But this one gives me all the children instead.

1 REPLY 1

shan
Graph Buddy

One way to do this is using ALL, as you suggested:

MATCH (a:A)-[: HAS_CHILD]->(c:Child)-[: HAS_ITEM]->(i:Item)
WITH a, COLLECT(DISTINCT i) AS items,  COLLECT(DISTINCT c) AS children
UNWIND items AS item
WITH a, item, children
WHERE ALL(c IN children WHERE((c)-[:HAS_ITEM]->(item)))
RETURN a, item

Here is a more efficient cypher that does not use ALL:

MATCH (a:A)-[: HAS_CHILD]->(c:Child)-[: HAS_ITEM]->(i:Item)
WITH a, COLLECT(i) AS items, COLLECT(DISTINCT c) AS children
UNWIND items AS item
WITH a, item, SIZE(COLLECT(item)) AS item_size, SIZE(children) AS children_size
WITH a, item WHERE item_size=children_size
RETURN a, item