0
votes

i'm new to neo4j.

I created this example:

//         (Node2)
//         /     \
//   Rel2 /       \ Rel3
//       /         \
// (Node1) ------> (Node3)
//          Rel1
// 
// create nodes
CREATE
(n1:Node1{id:1,rights:["admin","user"]}),
(n2:Node2{id:2,rights:["admin","user"]}),
(n3:Node3{id:3,rights:["admin","user"]})
// create relationships
CREATE (n1)-[r1:Rel1{id:11,rights:["admin"]}]->(n3)
CREATE (n1)-[r2:Rel2{id:12,rights:["admin","user"]}]->(n2)
CREATE (n2)-[r3:Rel3{id:13,rights:["admin","user"]}]->(n3)
RETURN n1,n2,n3,r1,r2,r3

Each node and relationship has a property array with some rights values. I want to create a query that gives me (shortest) paths between two nodes with specified properties. Example:

User has rights 'admin', the path should be:

(Node1)-[Rel1]->(Node3)
(Each node and releationship has the 'admin' String in the 'rights' property.)

If the user has the right 'user', the path should be:

(Node1)-[Rel2]-(Node2)-[Rel3]-(Node3)
(Because the Rel1 relation didn't have the 'user' String in the 'rights' property.)

At first i tried this query that worked:

WITH ["admin","otherRight"] AS usersRights
MATCH path=allShortestPaths((n1:Node1{id:1})-[*..4]-(n2:Node3{id:3})) 
WITH *, relationships(path) AS rels, nodes(path) as nodes
WHERE ANY (rel IN rels WHERE ANY(r IN rel.rights WHERE r IN usersRights))
AND ANY (node IN nodes WHERE ANY(r IN node.rights WHERE r IN usersRights))
RETURN path

Then i replaced the 'admin' with 'user', but this query didn't work (has no rusults):

WITH ["user","otherRight"] AS usersRights
MATCH ... // same as above
...
RETURN path

The follwing query matches my needed result, but in this case, i would have to make several queries to get the desired result (shortest paths) for depth n.

WITH ["user","otherRight"] AS usersRights
MATCH path=(n1:Node1{id:1})-[r1]-(n2)-[r2]-(n3:Node3{id:3}) 
WHERE ANY(r IN n1.rights WHERE r IN usersRights)
AND ANY(r IN r1.rights WHERE r IN usersRights)
AND ANY(r IN n2.rights WHERE r IN usersRights)
AND ANY(r IN r2.rights WHERE r IN usersRights)
AND ANY(r IN n3.rights WHERE r IN usersRights)
RETURN path

Is it possible to create a cypher query that gives me the disired results ?

Thanks.

1

1 Answers

0
votes

Your first query has a WITH clause separating the MATCH and WHERE clauses, which prevents the WHERE clause from affecting the behavior of the allshortestpath() function. Therefore, the function was just returning the shortest path(s) without testing the nodes and relationships.

Try this, instead:

WITH ["admin","otherRight"] AS usersRights
MATCH path=allShortestPaths((n1:Node1{id:1})-[*..4]-(n2:Node3{id:3})) 
WHERE
  ANY (rel IN relationships(path) WHERE ANY(r IN rel.rights WHERE r IN usersRights)) AND
  ANY (node IN nodes(path) WHERE ANY(r IN node.rights WHERE r IN usersRights))
RETURN path;