0
votes

I have a graph where green nodes may be linked to one or many red nodes which then link to a set of blue nodes. Red nodes also have an amt property which indicate the minimum number of blue nodes in the set which need to be matched in order to 'satisfy' the red node. A given set of blue nodes 'qualify' for a green node if the set satisfies all of the green node's red neighbours.

Example

enter image description here

enter image description here

How would a write a cypher query to return all qualifying green nodes for a given set of blue nodes?

I came up with the following that returns green nodes if all blue nodes of its red neighbours are matched. However, I don't need to match all but rather the amt specified for each red node.

MATCH (g:Green)-->(r:Red)-->(b:Blue)
WITH g, COLLECT(b.name) AS myset
WHERE ALL(n in myset where n in ["1", "2", "3", "4", "8", "9", "11"])
RETURN p
2

2 Answers

2
votes

First you need to find all the green candidates, and then check them through the red nodes:

WITH ["1", "2", "3", "4", "8", "9", "11"] AS blues
MATCH (g:Green)-[:requires]->(r:Red)-[:contains]->(b:Blue) WHERE b.name IN blues

WITH distinct g, blues
MATCH (g)-[:requires]->(r:Red)
OPTIONAL MATCH (r)-[:contains]->(b:Blue) WHERE b.name IN blues

WITH g, r, size(collect(DISTINCT b)) AS bCount
WITH g, collect([r.amt, bCount]) AS test
WITH g WHERe all(t IN test WHERE t[0] <= t[1])
RETURN g
0
votes

This query should return the Green nodes whose "required" Red nodes all have at least their individually required amt of "contained" Blue nodes:

MATCH (g:Green)-[:requires]->(r:Red)
WITH g, r, SIZE((r)-[:contains]->(:Blue)) AS cnt
WITH g, COLLECT({r: r, cnt: cnt}) AS data
WHERE ALL(d IN data WHERE d.cnt >= d.r.amt)
RETURN g;