2
votes

We have a tree of nodes. Some of the nodes are marked as red. we also have a DAG of users (green) potentially inside nested in groups (yellow). users and groups can see red nodes (there is no 'see' relation to non-red nodes)

Data model

Is it possible to write a cypher query that for given user U and node N checks (or return N) if U (directly or indirectly via groups) can see all red nodes on the path from root (id = 0) to the N?

I define the structure so any the changes are possible if needed.

examples:

  • condition is NOT satisfied for U=12 and (N = 3 or N = red above 3)
  • condition is satisfied for U = 7 and N = 3

My attempts:

I can easily select all read nodes from the root to N. I can easily select path from U to a red node on the path. but I don't know how to define the 'all' restriction. Is it possible?

Link to the Neo4j console: http://console.neo4j.org/?id=bigdba

The graph's source:

create (n1:node), (n2:node), (n3:node:red {name:'red'}),
(n1)-[:contains]->(n2), (n2) - [:contains] -> (n3),
(n3) - [:contains] -> (n4:node),
(n2) - [:contains] -> (n5:node),
(n5) - [:contains] -> (n6:node),
(n5) - [:contains] -> (n7:node:red {name:'red'}),

(u1:user) - [:inside] -> (g1:group),
(u1) - [:inside] -> (g2:group),
(u2:user) - [:inside] -> (g1),
(g1) - [:inside] -> (g3:group),

(g3) - [:see] -> (n3),

(u3:user) - [:see] -> (n7)
1

1 Answers

3
votes

Here is a solution using filter and all functions:

// match the path between root and n
MATCH p = (r:node)-[*]->(n:node) WHERE id(r) = 0 AND id(n) = 3
// match user u
MATCH (u) WHERE id(u) = 7
// filter all red nodes to the r list
WITH u, p, filter(node in nodes(p) where node:red) as reds
// return true if u can reach all red node
RETURN ALL(red in reds where (u)-[:inside*0..]->(:group)-[:see]->(red))