user1848018
user1848018

Reputation: 1106

Potential inconsistency in creating relationships in cypher when we don't use directions

I am getting confused with the way relationships are created through cypher. I was under the impression that _src-[:likes]- _dst creates a bidirectional relationship but looks like that is not the case as _src-[:likes]- _dst == _src<-[:likes]- _dst (example provided below)
Let's say I create the following graph but using the _src[:likes]-_dst notation ( using '-' as opposed to '->')

create
(_u1 {type:"User",`name`:"u1",userId:'u1' })  , (  _u2 {type:"User",`name`:"u2",userId:'u2'} )  , (  _u3 {type:"User",`name`:"u3",userId:'u3' })  , (  _u4 {type:"User",`name`:"u4",userId:'u4' })  , (  _u5 {type:"User",`name`:"u5",userId:'u5'}) ,  (_u6 {type:"User",`name`:"u6",userId:'u6'}), 
 (_f1 {type:"Item",`name`:"f1",itemId:'f1' })  , (  _f2 {type:"Item",`name`:"f2",itemId:'f2' })  , (  _f3 {type:"Item",`name`:"f3",itemId:'f3' })  , (  _f4 {type:"Item",`name`:"f4",itemId:'f4'}) ,  (_f5 {type:"Item",`name`:"f5",itemId:'f5'}),  
_u1-[:`likes`{likeValue:3}]-_f1 , _u1-[:`likes` {likeValue:13}]-_f2 , _u1-[:`likes` {likeValue:1}]-_f3 , _u1-[:`likes` {likeValue:5}]-_f4,
 _u2-[:`likes`{likeValue:7}]-_f1 , _u2-[:`likes` {likeValue:13}]-_f2 ,  _u2-[:`likes` {likeValue:1}]-_f3,
 _u3-[:`likes`{likeValue:5}]-_f1 , _u3-[:`likes` {likeValue:8}]-_f2 , _u4-[:`likes`{likeValue:5}]-_f1
 ,_u5-[:`likes` {likeValue:8}]-_f2,_u6-[:`likes` {likeValue:8}]-_f2; 

My impression was this way, you tell neo4j to created a bidirectional relationship. Now, look at the following query

neo4j-sh (?)$ start n=node(*) match n-[:likes]->m where has(n.type) and n.type='User' return n,m;
==> +-------+
==> | n | m |
==> +-------+
==> +-------+
==> 0 row 

But the opposite works

neo4j-sh (?)$ start n=node(*) match n-[r]->m where has(n.type) and n.type="Item" return n,m limit 3;
==> +-----------------------------------------------------------------------------------------+
==> | n                                          | m                                          |
==> +-----------------------------------------------------------------------------------------+
==> | Node[7]{type:"Item",name:"f1",itemId:"f1"} | Node[4]{type:"User",name:"u4",userId:"u4"} |
==> | Node[7]{type:"Item",name:"f1",itemId:"f1"} | Node[3]{type:"User",name:"u3",userId:"u3"} |
==> | Node[7]{type:"Item",name:"f1",itemId:"f1"} | Node[2]{type:"User",name:"u2",userId:"u2"} |
==> +-----------------------------------------------------------------------------------------+ 

The question is why a-[:likes]-b = a<-[:likes]-b ?
Now I create two more nodes and a relationship as instructed in the Cypher manual

    create (_u7 {type:"User",`name`:"u7",userId:'u7' });
    create (_f7 {type:"Item",`name`:"f7",itemId:'f7' });
 start src=node(*),dst=node(*) where src.name='u7' and dst.name='f7' create src-[:likes{likeValue:3}]-dst;
    neo4j-sh (?)$ start n=node(*) match n-[r]->m where has(n.type) and n.type="User" return n,m limit 3;
    ==> +-------+
    ==> | n | m |
    ==> +-------+
    ==> +-------+
    ==> 0 row 

same results, we can't query from User to Item but we can from Item to User
now if use the following method things change

create (_u {type:"User",`name`:"u8",userId:'u8' })  , (  _f {type:"User",`name`:"f8",userId:'f8'} ), _u-[:likes{likeValue:2}]-_f;
neo4j-sh (?)$ start n=node(*) match n-[r]->m where has(n.type) and n.type="User" return n,m limit 3;
==> +-------------------------------------------------------------------------------------------+
==> | n                                           | m                                           |
==> +-------------------------------------------------------------------------------------------+
==> | Node[19]{type:"User",name:"f8",userId:"f8"} | Node[18]{type:"User",name:"u8",userId:"u8"} |
==> +-------------------------------------------------------------------------------------------+ 

What is going on? These are my questions
1- Why create _src-[:likes]-_dst does not create a bidirectional relationship?
2- If it can't then why even allow _src-[:likes]-_dst for relationship creation? Why not force people to use directions when creating relationships?
3- What is the difference between the two methods I used to create relationships? (u7-f7 and u8-f8)

Upvotes: 0

Views: 73

Answers (1)

Luanne
Luanne

Reputation: 19373

You can't create a bidirectional relationship using _src[:likes]-_dst

In Neo4j, a relation can and must only have a single direction. So to represent bidirectional, you have two options:

a) Create the relation with a direction but ignore when querying (_src[:likes]-_dst will match both directions when part of a match clause)

b) Create two relations- one in either direction

It appears that if you execute a create without a direction such as _src[:likes]-_dst, an incoming relation is created for _src

Upvotes: 3

Related Questions