0

Let's consider a trivial graph with a directed relationship:

CREATE 
  (`0` :Car {value:"Ford"})
, (`1` :Car {value:"Subaru"})
, (`0`)-[:`DOCUMENT` {value:"DOC-1"}]->(`1`);

The following query MATCH (n1:Car)-[r:DOCUMENT]-(n2:Car) RETURN * returns:

╒══════════════════╤══════════════════╤═════════════════╕
│"n1"              │"n2"              │"r"              │
╞══════════════════╪══════════════════╪═════════════════╡
│{"value":"Subaru"}│{"value":"Ford"}  │{"value":"DOC-1"}│
├──────────────────┼──────────────────┼─────────────────┤
│{"value":"Ford"}  │{"value":"Subaru"}│{"value":"DOC-1"}│
└──────────────────┴──────────────────┴─────────────────┘

The graph defines only a Ford->Subaru relationship, why are two relationships?
How to interpret the reversed one (line 1; not specified in the CREATE) statement?

Note: This is a follow-up to Convert multiple relationships between 2 nodes to a single one with weight asked by me earlier. I solved my problem, but I'm not convinced my answer is the best solution.

Marek Grzenkowicz
  • 17,024
  • 9
  • 81
  • 111

1 Answers1

1

Your MATCH statement here doesn't specify the direction, therefore there are two possible paths that will match the pattern (remember that the ordering of nodes in the path is important and distinguishes paths from each other), thus your two answers.

If you specify the direction of the relationship instead you'll find there is only one possible path that matches:

MATCH (n1:Car)-[r:DOCUMENT]->(n2:Car) 
RETURN *

As for the question of why we get two paths back when we omit the direction, remember that paths are order-sensitive: two paths that have the same elements but with a different order of the elements are different paths.

To help put this into perspective, consider the following two queries:

# Query 1
MATCH (n1:Car)-[r:DOCUMENT]-(n2:Car) 
WHERE n1.value = 'Ford'
RETURN *

╒══════════════════╤══════════════════╤═════════════════╕
│"n1"              │"n2"              │"r"              │
╞══════════════════╪══════════════════╪═════════════════╡
│{"value":"Ford"}  │{"value":"Subaru"}│{"value":"DOC-1"}│
└──────────────────┴──────────────────┴─────────────────┘

# Query 2
MATCH (n1:Car)-[r:DOCUMENT]-(n2:Car) 
WHERE n1.value = 'Subaru'
RETURN *

╒══════════════════╤══════════════════╤═════════════════╕
│"n1"              │"n2"              │"r"              │
╞══════════════════╪══════════════════╪═════════════════╡
│{"value":"Subaru"}│{"value":"Ford"}  │{"value":"DOC-1"}│
└──────────────────┴──────────────────┴─────────────────┘

Conceptually (and also used by the planner, in absence of indexes), to get to each of the above results you start off with the results of the full match as in your description, then filter to the only one which meets the given criteria.

The results above would not be consistent with the original directionless match query if that original query only returned a single row instead of two.


Additional information from the OP

It will take a while to wrap my head around it, but it does work this way and here's a piece of documentation to confirm it's by design:

When your pattern contains a bound relationship, and that relationship pattern doesn’t specify direction, Cypher will try to match the relationship in both directions.

MATCH (a)-[r]-(b)
WHERE id(r)= 0
RETURN a,b

This returns the two connected nodes, once as the start node, and once as the end node.

Marek Grzenkowicz
  • 17,024
  • 9
  • 81
  • 111
InverseFalcon
  • 29,576
  • 4
  • 38
  • 51
  • For me, the query without specified direction means *match any direction that you find'll in the graph*, but it must be a relationship that's actually there. What's the point of returning a nonexistent one? – Marek Grzenkowicz Aug 11 '18 at 06:51
  • I don't follow. There is nothing nonexistent here. The relationship exists, but since you haven't specified the direction there are two possible paths that match in the graph. Both path exists, they just happen to use the same nodes and the same relationship, just the start and end nodes are switched and thus the path goes in a different direction. – InverseFalcon Aug 11 '18 at 09:47
  • Here's what is confusing for me - I am creating 3 objects (2 nodes and 1 relationship) and then a query returns 4 objects. What I am looking for is an equivalent of `SELECT *` of the relational world. – Marek Grzenkowicz Aug 11 '18 at 18:00
  • 1
    The query is returning the same objects, just in a different order. There are two possible paths matching the given pattern, involving the same nodes and the same relationship, the difference is the starting and ending node of the path. Paths are order-sensitive. If you want to enforce only one possible way to traverse through the relationship, you need to have a direction on it. – InverseFalcon Aug 11 '18 at 21:03