问题
Starting from an item recommended by people, is there a way to filter on a person property, such as age, while traversing at long distance friendship relationships? For instance in the following cypher query, I'd like to only traverse nodes of person +18y, not just filtering on p's age.
MATCH path = (:Fruit {Name: 'Apple'}) <-[:LIKES]- (:Person) -[:FRIENDOF*1..5]- (p:Person) -[:LIKES]-> (:Device {Name: 'iPhone'}) return path
UPDATE more details :
In this exemple the graph contains molecules and scaffolds resulting of stripping off side chains and rings recursively.
MATCH path=(:Molecule {Name: 'mol25'}) -[:hasSubstructure*1..3]- (s:Scaffold) <-[:hasSubstructure]- (:Molecule)
RETURN path

Molecules are shown in blue and scaffold in red named after their number of rings. As we can see, starting from mol25, we have a structure with a single ring at two edges distance.
Hence, I filter on the number of rings:
MATCH p=(:Molecule {Name: 'mol25'}) -[:hasSubstructure*1..3]- (s:Scaffold) <-[:hasSubstructure]- (:Molecule)
WHERE s.Num_Rings > 1
RETURN p
We get the same picture! The scaffold bearing a single ring is still present. Worse is to come!

Now we extract distinct scaffold nodes from using the previous queries, first without filtering on number of rings.
MATCH p=(:Molecule {Name: 'mol25'}) -[:hasSubstructure*1..3]- (s:Scaffold) <-[:hasSubstructure]- (:Molecule)
RETURN distinct id(s) as ID, s.Name, s.Size, s.Num_Rings
We expect 7 scaffold nodes in return... we only get 4. Filtering on number of rings returns the same results.
MATCH p=(:Molecule {Name: 'mol25'}) -[:hasSubstructure*1..3]- (s:Scaffold) <-[:hasSubstructure]- (:Molecule)
WHERE s.Num_Rings > 1
RETURN DISTINCT id(s), s.Name, s.Size, s.Num_Rings
Starting from another molecule than mol25 and using UNWIND to extract nodes from the path, it properly returns all scaffold nodes and filtered one without and with the WHERE condition respectively.
MATCH p=(m:Molecule) -[:hasSubstructure*1..4]-> (s:Scaffold)
WHERE id(m)=9 and s.Num_Rings > 1
UNWIND nodes(p) as n
RETURN id(n), n.Name, n.Num_Rings, n.Size, n.Smiles
But again, returning the path p instead we get the correct graph when restricting on the -[:hasSubstructure*1..4]-> direction, but not without the direction restriction -[:hasSubstructure*1..4]-.
I'd appreciate if anyone would help sorting this out.

回答1:
Some points here :
Hence, I filter on the number of rings:
MATCH p=(:Molecule {Name: 'mol25'}) -[:hasSubstructure*1..3]- (s:Scaffold) <-[:hasSubstructure]- (:Molecule)
WHERE s.Num_Rings > 1
RETURN p
Don't forget that by specifying variable length paths, it is totally possible that the path going from mol25
to scaffold4
to scaffold1
to other scaffold4
and then to other molecule
will be valid, as the end of the edge is a molecule and the node before has a Num_Rings > 1
, indepedently of the other intermediate nodes values of Num_Rings.
So the intermediate nodes can be anything, if you want to restrict to the scaffolds with a value > 1, you should use a ALL
clause :
This query seems to do the trick based with the following Neo4j console : http://console.neo4j.org/r/7f5hc4 (property values a bit different but yeah..)
MATCH p=(m:Molecule { id: 566 })-[r:HAS_SUBSTRUCTURE*1..3]-(s:Scaffold)<-[:HAS_SUBSTRUCTURE]-(:Molecule)
USING INDEX m:Molecule(id)
WHERE ALL (x IN tail(nodes(p))[0..size(nodes(p))-2]
WHERE 'Scaffold' IN labels(x) AND x.rings > 29)
RETURN p
Explanations :
- Match the path like you do
- USING INDEX, by my tests with PROFILE, I saw the molecule(id) index was not used, so I help Cypher a bit
- The
tail(nodes(p))[0..size(nodes(p))-2]
are the nodes in the path between the two molecules, note thatnodes(p)[1..size(nodes(p))-2]
is equivalent - I assert that these nodes have
ALL
the label scaffold and a Num_Rings value > 29 (here 29 because it is randomized from Graphgen)
回答2:
Seems you can use a simple WHERE
clause, and filter appropriately.
MATCH path = (:Fruit {Name: 'Apple'})<-[:LIKES]-
(intermed:Person)-[:FRIENDOF*1..5]-(p:Person)
-[:LIKES]->(:Device {Name: 'iPhone'})
WHERE intermed.age >= 18 AND
p.age >= 18
return path
回答3:
Here is a long answer, with more details.
In this exemple the graph contains molecules and scaffolds resulting of stripping off side chains and rings recursively.
MATCH path=(:Molecule {Name: 'mol25'}) -[:hasSubstructure*1..3]- (s:Scaffold) <-[:hasSubstructure]- (:Molecule)
RETURN path

Molecules are shown in blue and scaffold in red named after their number of rings. As we can see, starting from mol25, we have a structure with a single ring at two edges distance.
Hence, I filter on the number of rings:
MATCH p=(:Molecule {Name: 'mol25'}) -[:hasSubstructure*1..3]- (s:Scaffold) <-[:hasSubstructure]- (:Molecule)
WHERE s.Num_Rings > 1
RETURN p
We get the same picture! The scaffold bearing a single ring is still present. Worse is to come!

Now we extract distinct scaffold nodes from using the previous queries, first without filtering on number of rings.
MATCH p=(:Molecule {Name: 'mol25'}) -[:hasSubstructure*1..3]- (s:Scaffold) <-[:hasSubstructure]- (:Molecule)
RETURN distinct id(s) as ID, s.Name, s.Size, s.Num_Rings
We expect 7 scaffold nodes in return... we only get 4. Filtering on number of rings returns the same results.
MATCH p=(:Molecule {Name: 'mol25'}) -[:hasSubstructure*1..3]- (s:Scaffold) <-[:hasSubstructure]- (:Molecule)
WHERE s.Num_Rings > 1
RETURN DISTINCT id(s), s.Name, s.Size, s.Num_Rings
Starting from another molecule than mol25 and using UNWIND to extract nodes from the path, it properly returns all scaffold nodes and filtered one without and with the WHERE condition respectively.
MATCH p=(m:Molecule) -[:hasSubstructure*1..4]-> (s:Scaffold)
WHERE id(m)=9 and s.Num_Rings > 1
UNWIND nodes(p) as n
RETURN id(n), n.Name, n.Num_Rings, n.Size, n.Smiles
But again, returning the path p instead we get the correct graph when restricting on the -[:hasSubstructure*1..4]-> direction, but not without the direction restriction -[:hasSubstructure*1..4]-.
I'd appreciate if anyone would help sorting this out.

来源:https://stackoverflow.com/questions/30619173/filtering-on-node-property-in-long-distance-path