Reputation: 3130
My graph has the only one type of relationship with no labels, no properties etc on them. Just directed relationships called NT
.
Each node has a set of properties. Based on that properties I want to show up all the paths (chains) where the start node has codeqty > 0
along with codes
property but all the next nodes are codeqty = 0
(with empty codes
property) until there happened another node in the chain with codeqty > 0
AND different codes
property by its text OR regardless codes
property.
So I need to get all the nodes with any depth like this pseudocode pattern:
(n)-[:NT]->(m) where n.codeqty > 0 and m.codeqty = 0
(as the start point condition)
...
(m)-[:NT]->(p) where m.codeqty = 0 and p.codeqty > 0 and n.codes <> p.codes
(as the end point condition)
OR just by meeting any next p.codeqty > 0
regardless codes
property like
(m)-[:NT]->(p) where m.codeqty = 0 and p.codeqty > 0
(as the end point condition)
I need to show up the (shortest or any) path starting with (n)->...->(m)
ending by (m)
because (p)
does not belong to this chain by the stop condition.
Could it be also limited by depth as the option?
By the way, is it really possible to do this way by using nodes properties, not relationships properties? If not, please make a snippet on how to do it.
Thank you so much!
PS. Any version of neo4j is welcome. I am using the very latest 2.20
UPD
I have an idea like this (n,p,m variables could be different from above but you got the idea)
MATCH (n)-[:NT]->(p)<-[:NT]-(m) WHERE n.codes = m.codes AND n.codeqty > 0 AND p.codeqty = 0
It seems to be OK for 2 hops:
MATCH (n)-[:NT*1..2]->(p)<-[:NT*1..2]-(m) WHERE n.codes = m.codes AND n.codeqty > 0 AND p.codeqty = 0
It starts messing up since 3 or more hops:
MATCH (n)-[:NT*1..3]->(p)<-[:NT*1..3]-(m) WHERE n.codes = m.codes AND n.codeqty > 0 AND p.codeqty = 0
As far as I was able to check manually.
I feel it could be perfectly done and filtered out by using something like SQL window functions like PARTITION BY ROW_NUMBER for SQL Server. I don't know any Cypher equivalent for that jazz. Do you know?!
Upvotes: 2
Views: 1642
Reputation: 41706
What you are looking for are variable length paths like in your last examples, combined with collection functions and predicates.
MATCH path = (n)-[:NT*1..3]->(p)
WHERE n.codeqty > 0
AND ALL(x in tail(nodes(path)) WHERE x.codeqty = 0)
AND NOT (p)-[:NT]->()
if you want to compare nodes within a collection you'll have to resort to an indexed based accesss
WITH nodes(path) as nodes
AND ALL(idx in range(0,size(nodes)-2) WHERE nodes[idx].codes <> nodes[idx+1].codes)
Upvotes: 4