Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
12-18-2019 01:02 PM
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.
12-18-2019 08:38 PM
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
All the sessions of the conference are now available online