1

Suppose, we model couples with 2 vertex labels, female and male, and with a single edge label, dates. The direction of the edge is always from female to male.

The expected query result list are couples, where there is a non-directed path from a start vertex to the vertices of each couple, distinct.

In other words the result should contain the edge list of the connected components of the graph, where the given vertex is present.

Please note, that there can be loops if the original graph is converted to a non-directed graph.

Sample graph

Filter criterion: { name: 'Adam' }

Expected result set:

Alice-[:dates]->Adam
Alice-[:dates]->Bob
Chloe-[:dates]->Bob
...
Eve-[:dates]->Edgar

Uhura-[:dates]->Spock is NOT part of the result set, since there is no connection between Adam and (Uhura or Spock).

The following solution works, but it has poor performance, so it can't be used in production:

match path = ()-[:dates*]-()
where any(node in to_jsonb(nodes(path)) where node.properties.name = 'Adam')
return distinct path;

(Or return distinct edges(path), but AgensBrowser does not like to return the edges of a path).

Could you please help me with some advices for a better solution? Thanks.

Test data:

create
  (alice: female { name: 'Alice'}),
  (barbara: female { name: 'Barbara'}),
  (chloe: female { name: 'Chloe'}),
  (diane: female { name: 'Diane'}),
  (eve: female { name: 'Eve'}),
  (uhura: female { name: 'Uhura'}),
  (adam: male { name: 'Adam'}),
  (bob: male { name: 'Bob'}),
  (charles: male { name: 'Charles'}),
  (daniel: male { name: 'Daniel'}),
  (edgar: male { name: 'Edgar'}),
  (spock: male { name: 'Spock'})
create (alice)-[:dates]->(adam),
  (alice)-[:dates]->(bob),
  (barbara)-[:dates]->(bob),
  (barbara)-[:dates]->(charles),
  (barbara)-[:dates]->(edgar),
  (chloe)-[:dates]->(bob),
  (chloe)-[:dates]->(daniel),
  (chloe)-[:dates]->(edgar),
  (diane)-[:dates]->(edgar),
  (eve)-[:dates]->(edgar),
  (uhura)-[:dates]->(spock);
jupi
  • 105
  • 5

1 Answers1

1

I tried to reenact your query in Agensgraph, but the last match query did not work for me, so I wasn't able to check out its explain.

Here is the query I made to retrieve the same result you want to.

match (f:female)<-[r:dates*]->(m:male{name:'Adam'}) with distinct f
match p = ((f)-[:dates]->(m:male)) return p;

--------------------------------------------------------------------------
[female[73.1]{"name": "Alice"},dates[71.23][73.1,74.1]{},male[74.1]{"name": "Adam"}]
[female[73.1]{"name": "Alice"},dates[71.24][73.1,74.2]{},male[74.2]{"name": "Bob"}]
[female[73.2]{"name": "Barbara"},dates[71.25][73.2,74.2]{},male[74.2]{"name": "Bob"}]
[female[73.2]{"name": "Barbara"},dates[71.26][73.2,74.3]{},male[74.3]{"name": "Charles"}]
[female[73.2]{"name": "Barbara"},dates[71.27][73.2,74.5]{},male[74.5]{"name": "Edgar"}]
[female[73.3]{"name": "Chloe"},dates[71.28][73.3,74.2]{},male[74.2]{"name": "Bob"}]
[female[73.3]{"name": "Chloe"},dates[71.29][73.3,74.4]{},male[74.4]{"name": "Daniel"}]
[female[73.3]{"name": "Chloe"},dates[71.30][73.3,74.5]{},male[74.5]{"name": "Edgar"}]
[female[73.4]{"name": "Diane"},dates[71.31][73.4,74.5]{},male[74.5]{"name": "Edgar"}]
[female[73.5]{"name": "Eve"},dates[71.32][73.5,74.5]{},male[74.5]{"name": "Edgar"}]
(10 rows)

Frankly saying, I am not so sure about the performance of above query when the volume of data is huge.

Please leave me the feedback after running the query.

Edited on 25 Mar.

Could this be the solution for your case?

match p = allshortestpaths( (f:female)<-[r:dates*]->(m:male) )
where any(node in to_jsonb(nodes(p)) where node.properties.name starts with 'Adam' )
return p;

enter image description here

  • Thank you, your solution works for the example and your efforts are much appreciated. In real life cases we have more complex criteria than {name:'Adam'}, so we could use only `any(node in to_jsonb(nodes(path)) where ...)` and `all(node in to_jsonb(nodes(path)) where ...)` style of expressions. That caused poor performance especially if there was a loop on the undirected path. Do let's say we have a condition "name starts with Adam" instead of "name equals Adam". Do you know an effective solution for that? Thanks. – jupi Mar 05 '19 at 10:54
  • Since the answer is correct for the original problem, I will mark it as accepted. However if anybody could give an answer to the case of complex conditions (see my last comment) that would be great. Thanks. – jupi Mar 06 '19 at 07:25