Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
01-20-2022 07:05 PM
I want to convert one gremlin query which is similar to below one. In repeat statement, it will traverse till EndNode with validating each InNode1 in that path with given conditions.
If any InNode1 in that path doesnt satisfy then result will be Zero.
g.V().hasLabel('Person').has('name','John')
.repeat(.out('OutNode1').in('InNode1').has('Status',within('Active','InActive'))
.not(has('oStatus',within('Suspended','Closed'))).where(.out('OutNode2').not(has('name',within('SampleVal1','SampleVal2'))))
)
.until(__.in('MeetsEndNode'))
.in('MeetsEndNode')
I converted above query into cypher like below. Here filtering applies to last node in that path. It is not checking all InNode1 in that path.
MATCH (p:Person {name: 'John'}) - [:OutNode1|InNode1*] - (relNode) <-[:MeetsEndNode]-(endNode)
WHERE relNode.Status in ['Active','InActive']
AND NOT relNode.oStatus in ['Suspended','Closed']
AND NOT exists { MATCH (relNode) - [:OutNode2] -> (o)
WHERE o.name in ['SampleVal1','SampleVal2'] }
RETURN endNode
Please suggest how we can achieve the same functionality in cypher.
01-21-2022 06:29 AM
I think this should be work (I put (relNode)-[:OutNode2]->(o)
in first match
clause):
MATCH (p:Person {name: 'John'})-[:OutNode1|InNode1*]-(relNode)<-[:MeetsEndNode]-(endNode), (relNode)-[:OutNode2]->(o)
WHERE relNode.Status in ['Active','InActive']
AND NOT relNode.oStatus in ['Suspended','Closed']
AND NOT o.name in ['SampleVal1','SampleVal2']
RETURN endNode
01-21-2022 09:57 AM
@giuseppe.villani ... Thanks for your response.
I am simplifying my query . Below screen shot shows the how data model looks like
If any of the InNode in that path fails with given below validation then last InNode should not come in the result set. If all InNode in that path passed with all validations then FInal InNode should come in the result.
MATCH (n:Person {name:'John'}) - [:OutNode|InNode*] - (InNode)
WHERE InNode.Status in ['Active','InActive']
AND NOT InNode.oStatus in ['Suspended','Closed']
AND NOT exists { MATCH (InNode) - [:SubOutNode] -> (o) WHERE o.name in ['SampleVal1','SampleVal2'] }
Above code checks only the last InNode of that path. If last InNode passed with validation then it is giving the result. It is not checking all the InNodes present in the path. Kindly suggest how we can achieve this.
01-21-2022 01:39 PM
You'll need to use a path variable and the all() list predicate on the list of nodes in the path.
For example:
MATCH path = (n:Person {name:'John'}) - [:OutNode|InNode*] -()<-[:MeetsEndNode]-(endNode)
WHERE all(node IN nodes(path) WHERE node.Status in ['Active','InActive'] AND NOT node.oStatus in ['Suspended','Closed']
AND NOT exists {
MATCH (node) - [:OutNode2] -> (o)
WHERE o.name in ['SampleVal1','SampleVal2'] })
RETURN endNode
Though returning the path itself may be more useful for you.
You can also bound the nodes that are evaluated to exclude the first and last nodes of the path, so they apply to the nodes in the middle only:
...
WHERE all(node in nodes(path)[1..-1] WHERE ...
...
THAT SAID...I'm encountering syntax errors when trying to use existential subqueries within list predicates, something that seems buggy to me. I'm following up with that internally.
01-22-2022 07:18 AM
@andrew.bowman Thanks for your prompt response.
As you rightly mentioned, syntax error occuring when we use Not exists within list predicates. If i remove Not exists then query is executing without any errors and validating the node as expected.
MATCH path = (n:Person {Name:'John'}) - [:OutNode|InNode*] -()-[:EndNode]->(endNode)
WITH path,[i in nodes(path) where 'InNode' in labels(i)] as InNodes
WHERE ALL (i IN InNodes WHERE i.Status in ['Active','InActive'] AND NOT i.oStatus in ['Suspended','Closed'] AND NOT exists {
MATCH (i) - [:OutNode2] -> (o)
WHERE o.name in ['SampleVal1','SampleVal2'] })
RETURN path
Error is
Please let us know if you know any alternative for this error or any update from your internal team
01-22-2022 07:58 AM
Below query is working with relationship check (i)-[:OutNode2] -> () in list predications but not able to filter the relationship node with some condition like (i)-[:OutNode2] -> (o) WHERE o.name in ['SampleVal1','SampleVal2']
MATCH path = (n:Person {Name:'John'}) - [:OutNode|InNode*] -()-[:EndNode]->(endNode)
WITH path,[i in nodes(path) where 'InNode' in labels(i)] as InNodes
WHERE ALL (i IN InNodes WHERE i.Status in ['Active','InActive'] AND NOT i.oStatus in ['Supended','Closed'] AND (i)-[:OutNode2] -> () )
RETURN path
01-24-2022 02:54 PM
Still waiting to hear back if this syntax error is a bug.
We may be able to do a workaround with pattern comprehensions instead. Something like:
MATCH path = (n:Person {Name:'John'}) - [:OutNode|InNode*] -()-[:EndNode]->(endNode)
WITH path,[i in nodes(path) where 'InNode' in labels(i)] as InNodes
WHERE ALL (i IN InNodes WHERE i.Status in ['Active','InActive'] AND NOT i.oStatus in ['Suspended','Closed']
AND size([(i) - [:OutNode2] -> (o) WHERE o.name in ['SampleVal1','SampleVal2'] | 1]) = 0)
RETURN path
The pattern comprehension lets us express the limitations on the other node, o
, and if the size of the list from that comprehension is 0, that means no such matches were found.
02-07-2022 03:29 AM
@andrew.bowman Is there any update from your internal team on this issue ?
I have divided the condition into three parts for time being and it is working. I cannot do like this if more conditions getting added in other areas.
MATCH path = (n:Person {Name:'John'}) - [:OutNode|InNode*] -()
-[:EndNode]->(endNode)
WITH path,[i in nodes(path) where 'InNode' in labels(i)] as InNodes
WHERE ALL (i IN InNodes WHERE i.Status in ['Active','InActive']
AND NOT i.oStatus in ['Suspended','Closed']
AND (i) - [:OutNode2] -> ()
AND NOT (i) - [:OutNode2] -> ( {name:'SampleVal1'})
AND NOT (i) - [:OutNode2] -> ( {name:'SampleVal2'}) )
02-07-2022 09:56 AM
Sorry, nothing new to report here. At this time please continue to use the workaround provided.
All the sessions of the conference are now available online