If the number of properties is greater than n, ret

2020-05-05 17:40发布

问题:

This question is a direct extension of a question I asked previously.

Say I have a graph database that looks like this:

Just like the previous question I asked, the only really interesting thing about this is that SomeProperty can be 'Yes' or 'No'.

In the top row, 1 of the 3 nodes have a 'Yes' for this property.

On the bottom row, there are 3 nodes have a 'Yes' for this property. The other 2 have a 'No'.

How do I write a Cypher query that returns only THE WHOLE the bottom row, by asking the question: Do either of these disjoint subgraphs have 2 or more values for SomeProperty = 'Yes'?

Previously, the brilliant @cybersam recommended using something like:

MATCH p=(:Person)-[:RELATED_TO*]->(:Person)
WHERE 2 < REDUCE(s = 0, x IN NODES(p) | CASE WHEN x. SomeProperty = 'Yes' THEN s + 1 ELSE s END)
RETURN p;

...which would return the matching paths. In this case, this would return

but I am trying to generalize this to return the whole set of 5 "B" nodes.

After struggling with this, I realize that I'm trying to create the 3 node subgraph, but not return it. I'm trying to use its existence as a way to return the supergraph of my match, and ignore any non-connected subgraphs! This is getting pretty complicated and I'm stumped.

Here is my code:

CREATE (albert:person {gender: 'Male', name: 'Albert', SomeProperty: 'Yes'})
CREATE (annie:person {gender: 'Female', name: 'Annie', SomeProperty: 'No'})
CREATE (adrian:person {gender: 'Female', name: 'Adrian', SomeProperty: 'No'})

CREATE (albert)-[r1:RELATED_TO]->(annie)
SET r1.relationship='related'
CREATE (annie)-[r2:RELATED_TO]->(adrian)
SET r2.relationship='related'

CREATE (bill:person {gender: 'Male', name: 'Bill', SomeProperty: 'Yes'})
CREATE (barb:person {gender: 'Female', name: 'Barb', SomeProperty: 'Yes'})
CREATE (barry:person {gender: 'Male', name: 'Barry', SomeProperty: 'Yes'})
CREATE (bart:person {gender: 'Male', name: 'Bart', SomeProperty: 'No'})
CREATE (bartholemu:person {gender: 'Male', name: 'Bartholemu', SomeProperty: 'No'})

CREATE (bill)-[r4:RELATED_TO]->(barb)
SET r4.relationship='related'
CREATE (barb)-[r5:RELATED_TO]->(barry)
SET r5.relationship='related'
CREATE (barry)-[r6:RELATED_TO]->(bart)
SET r6.relationship='related'
CREATE (bart)-[r7:RELATED_TO]->(bartholemu)
SET r7.relationship='related'

回答1:

This query will filter out all sub-paths from the results:

MATCH p=(a:person)-[:RELATED_TO*]->(b:person)
WHERE
  NOT ()-[:RELATED_TO]->(a) AND
  NOT (b)-[:RELATED_TO]->() AND
  2 < REDUCE(s = 0, x IN NODES(p) | CASE WHEN x. SomeProperty = 'Yes' THEN s + 1 ELSE s END)
RETURN p;

Explanation:

  • NOT ()-[:RELATED_TO]->(a) is true if the a node is not the at the end of a RELATED_TO relationship.
  • NOT (b)-[:RELATED_TO]->() is true if the b node is not at the start of a RELATED_TO relationship.

Therefore, a matching path cannot be a sub-path.



标签: neo4j cypher