0

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

Say I have a graph database that looks like this:

enter image description here

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

enter image description here

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'
Community
  • 1
  • 1
Monica Heddneck
  • 2,973
  • 10
  • 55
  • 89

1 Answers1

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.

cybersam
  • 63,203
  • 6
  • 53
  • 76
  • What does the `*` character in `[:RELATED_TO*]` do? – Monica Heddneck Apr 20 '16 at 00:27
  • The `*` in a relationship indicates a [variable length](http://neo4j.com/docs/stable/introduction-pattern.html#_variable_length) relationship. – cybersam Apr 20 '16 at 00:30
  • ah...I get it. It means "match any paths of any length, with respect to the RELATED_TO relationship." Thanks! – Monica Heddneck Apr 20 '16 at 21:51
  • `[:RELATED_TO*]` is equivalent to `:RELATED_TO*1..]`. In other words, by default a variable length relationship must have a length of at least 1 (not "any length"). You should read [the documentation](http://neo4j.com/docs/stable/introduction-pattern.html#_variable_length) to understand more about how to use variable length relationships. – cybersam Apr 20 '16 at 22:00
  • I have to be honest. Your answer works perfectly but I can't understand how it works. From what I read, the pseudocode is: 1) Match everything as a path which is one relationship away (?) 2) Ignore everything that is related to all nodes (??) 3) Keep based on `SomeProperty` I can't really figure this out! I've been at it all day :( – Monica Heddneck Apr 21 '16 at 02:02
  • I have updated my answer. Hopefully the extra info will help. – cybersam Apr 21 '16 at 02:09
  • I notice the query works the same even if the two NOT statements are omitted? I may have just came up with a lousy example. – Monica Heddneck Apr 21 '16 at 02:27
  • Using your code to generate the test data, I get different results for the 2 queries. With the `NOT` terms included, I get 1 result path (with 5 nodes). Without those terms, I get 3 paths returned. – cybersam Apr 21 '16 at 02:30
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/109743/discussion-between-monica-heddneck-and-cybersam). – Monica Heddneck Apr 21 '16 at 02:45