Query node path - Subset of node with property value filtering

Hello. I am very new in neo4j and cypher.

I have nodes between which there may be links.
Each node has a field, which I have now called a subject.
My task would be to be able to select the complete paths where the nodes following each other on the path have a certain subject.
Previously I used mongo dbt, there I used the $setIsSubset function to search for this.

Can someone give me a tutorial on how I can implement this in cypher .

MATCH p=(start:Annotation)-[:connection*1..100]->(end:Annotation)
WITH nodes(p) as path
  WHERE ANY(node in path WHERE node.SubjectId ="5f02e8254850751ffc044c8a" OR  node.SubjectId ="6493f28567d762570722e613")
RETURN path
LIMIT 150

I tried something like this, but this is obviously not a good solution.

Thanks for the help!

Hi @gergelyurbancsik :call_me_hand:

There's a whole documentation about the new Quantified Patter Matching syntax here.

In this case, you can start trying something like:

MATCH p=(start:Annotation)((a)-[:connection]->(b) WHERE a.SubjectId in ["5f02e8254850751ffc044c8a", "6493f28567d762570722e613"] and b.SubjectId in ["5f02e8254850751ffc044c8a", "6493f28567d762570722e613"]){1,100}(end:Annotation)
RETURN p //edited
LIMIT 150

You may like to add some conditions on your start and end node in order to avoid calculating the same thing multiple times tho.

1 Like

Hi @bennu_neo
First of all, thanks for the help, and the reply.
Maybe I explained it wrong, but this is not a good solution.
this will return only the two nodes for which the condition is met.
However, I want to get the full path back.

For example:
a=annotation
s=subject

a1(s0) - > a2(s1) -> a3(s2) -> a4(s3)
a5(s4) - > a2(s1) -> a3(s5) -> a4(s2)

find the graph where the subjects of the successive nodes are s1 and s2.
so this is true for the first, not for the second.
and I would like to get this result back:
a1(s0) - > a2(s1) -> a3(s2) -> a4(s3)

can you help me with this ?

Hello hello!

I just edited the answer to return p. The query should return path were all the elements along fulfill the where condition. It should return a path.

Hello @bennu_neo
maybe something is still misunderstood,
the longest path in my database:


Query for this:

MATCH p=(start:Annotation)-[:connection*1..100]->(end:Annotation)

RETURN p

ORDER BY length(p) DESC

LIMIT 1

within this graph there are two nodes where the two ids follow each other: 64a592c5868c0d0007218fef, 64a592c5868c0d0007218fee.

so if I substitute this into your query, I want to see the same result as the longest path query above, i.e. the full path.
instead I get the result shown in the picture:

Hello @gergelyurbancsik !

So you may like something like:

MATCH p =()(()-[:C]->()){,100}(b)-[:C]->(c)(()-[:C]->()){,100}()
WHERE b.name = "B"
AND c.name = "C"
RETURN p

Hello @bennu_neo
I think this is still not the expected result
For this query:

MATCH p =()(()-[:connection]->()){,100}(b)-[:connection]->(c) (()-[:connection]->()){,100}()
WHERE b.SubjectId ='5f02e8254850751ffc044c8a'
    AND c.SubjectId ='6493f28567d762570722e613'
RETURN p LIMIT 100

The result is:

And for this query:

MATCH p=(start:Annotation)((a)-[:connection]->(b)

WHERE a.SubjectId in ["5f02e8254850751ffc044c8a", "6493f28567d762570722e613"]

and b.SubjectId in ["5f02e8254850751ffc044c8a", "6493f28567d762570722e613"]){1,100}(end:Annotation)

RETURN p

LIMIT 150

The result is:

Update:
ahh, own mistake

With this query:

MATCH p =()(()-[:connection]->()){,100}(b)-[:connection]->(c) (()-[:connection]->()){,100}()

WHERE b.SubjectId in ["5f02e8254850751ffc044c8a", "6493f28567d762570722e613"]

and c.SubjectId in ["5f02e8254850751ffc044c8a", "6493f28567d762570722e613"]

RETURN p LIMIT 100


but this is still not the full length of the graph.
I'll have a closer look in the database.
Thanks for your help

Thanks @bennu_neo

And what happens if I want to include exactly these nodes anywhere on the graph ?
What operator can be used instead of IN ?
So now if I specify that I'm looking for 3 subjects, it will return subjects where, for example, 2 of the 3 follow each other, but the 3rd is not even listed.

Hello hello,

The IN operator has nothing to do with position of the nodes but it only enforce the desired condition.

MATCH p =()(()-[:connection]->()){,100}(b)-[:connection*]->(c)(()-[:connection]->()){,100}()
WHERE b.SubjectId in ["5f02e8254850751ffc044c8a", "6493f28567d762570722e613"]
and c.SubjectId in ["5f02e8254850751ffc044c8a", "6493f28567d762570722e613"]
RETURN p

This one should work for distances between your 2 targets bigger than 1. However, for more intricate scenarios, as always, I may say: "It depends". You can always fallback into path predicates as ANY but be aware those are not enforces runtime but are post traversal filters, so memory can grow a lot before noticing that many of the calculated paths are not valid.

1 Like