Neo4j Bidirectional Relationship - neo4j

Is there a way to create bidirectional relationship in Neo4j using Cypher? I would like the relationship to be bidirectional rather than making two unidirectional relationships in both directions For eg:
(A)<-[FRIEND]->(B)
Rather than:
(A)-[FRIEND]->(B)
(A)<-[FRIEND]-(B)
Thanks in advance :)

No, there isn't. All relationships in neo4j have a direction, starting and ending at a given node.
There are a small number of workarounds.
Firstly, as you've suggested, we can either have two relationships, one going from A to B and the other from B to A.
Alternatively, when writing our MATCH query, we can specify to match patterns directionlessly, by using a query such as
MATCH (A)-[FRIEND]-(B) RETURN A, B
which will not care about whether A is friends with B or vice versa, and allows us to choose a direction arbitrarily when we create the relationship.

According to this article: Modeling Data in Neo4j: Bidirectional Relationships
The strictly better choice is to create a relationship in an arbitrary direction and not specify the direction when querying:
MATCH (neo)-[:PARTNER]-(partner)
The engine is capable of traversing the edge in either direction. Creating the anti-directional edge is unnecessary and only serves to waste space and traversal time.

Related

neo4j : How to Create the bidirectional Relationships in graph database?

I tried to create bidirectional relationships by using this pattern (u1)-[:]-(u2) and also this one (u1)<-[:]->(u2).
but at the end result is directed to one part of the nodes from the first parenthesis to last one (u1)-[:]->(u2).
How to achieve bidirectional relationships here?
I think Neo4j cannot store bidirectional relationships.
No way around this, however, you can treat relationships as bidirectional when querying your graph.

Collapse Relationships Neo4j?

Is it possible to "collapse" relationships in neo4j? I'm trying to graph relationships between people, and they can be related in multiple different ways - a shared course, jointly authored paper, RT or tweet mention. Right now I'm modeling people, courses, papers, and tweets all as nodes. But what I'm really interested in is modeling the person-person relationships that go through these intermediary nodes. Is it possible to graph the implicit relationship (person-course-person) explicit (person-person), while still keeping the course as a node? Something like this http://catalhoyuk.stanford.edu/network/teams/ - slide 2 and 3.
Any other data modeling suggestions welcome as well.
Yes, you can do it. The query
MATCH(a:Person)-->(:Course)<--(b:Person)
CREATE (a)-[:IMPLICIT_RELATIONSHIP]->(b)
will crate a relationship with type :IMPLICIT_RELATIONSHIP between all people that are related to the same course. But probably you don't need it since you can transverse from a to b and from b to a without this extra and not necessary relationship. Also if you want a virtual relationship at query time to use in a projection you can use the APOC procedure apoc.create.vRelationship.
The APOC procedures docs says:
Virtual Nodes and Relationships don’t exist in the graph, they are
only returned to the UI/user for representing a graph projection. They
can be visualized or processed otherwise. Please note that they have
negative id’s.

Why neo4j don't allows not directed or bidirectional relationships at creation time?

I know that Neo4j requires a relationship direction at creation time, but allows ignore this direction in query time. By this way I can query my graph ignoring the relationship direction.
I also know that there are some workarounds for cases when the relationships are naturally bidirectional or not directed, like described here.
My question is: Why is it implemented that way? Has a good reason to not allow not directed or bidirectional relationships at creation time? Is it a limitation of the database architecture?
The Cypher statements like below are not allowed:
CREATE ()-[:KNOWS]-()
CREATE ()<-[:KNOWS]->()
I searched the web for an answer, but I did not find much. For example, this github issue.
Is strange to have to define a relationship direction to one that don't have it. It seems to me that i'm hurting the semantic of my graph.
EDIT 1:
To clarify my standpoint about a "semantic problem" (maybe the term is wrong):
Suppose that I run this simple CREATE statement:
CREATE (a:Person {name:'a'})-[:KNOWS]->(b:Person {name:'b'})
As result i have this very simple graph:
The :KNOWS relationship has a direction only because Neo4j requires a relationship direction at creation time. In my domain a knows b and b knows a.
Now, a new team member will query my graph with this Cypher query:
MATCH path = (a:Person {name:'a'})-[:KNOWS]-(b:Person {name:'b'})
return path
This new team member don't know that when I created this graph I considered that :KNOWS relationship is not directed. The result that he will see is the same:
By the result this new team member can think that only Person a consider knows Person b. It seems to me bad. Not for you? This make any sense?
Fundamentally, it boils down to the internals of how the data is stored on disk in Neo4j -- note Chapter 6 of the O'Reilly Neo4j e-book.
In the data structure of a relationship they have a "firstNode" and a "secondNode", where each is either the left or the right hand side of the relationship.
To flag a relationship as uni/bi-directional would require an additional bit per node, where I would argue it is better to retain the direction in the data store and just ignore direction during querying.
In Neo4j relationships are always directed.
But if you don't care about the direction, you can ignore the direction when querying.
MATCH (p1:Person {name:"me"})-[:KNOWS]-(p2)
RETURN p2;
And with MERGE you can also leave off the direction when creating.
MATCH (p1:Person {name:"me"})
MATCH (p2:Person {name:"you"})
MERGE (p1)-[:KNOWS]-(p2);
You only need 2 relationships if they really convey a different meaning, e.g. :FOLLOWS on Twitter.
It seems to me that i'm hurting the semantic of my graph.
I can't see why a < or > symbol used during creation of a relationship hurts the semantics of your graph if you are going to not use that symbol during matching (and thus treating that relationship as undirected/bidirectional).
Suppose that the syntax proposed by you is supported. Now how will you connect with an undirected relationship two nodes a and b? You still have two options:
CREATE (a)-[:KNOWS]-(b)
CREATE (b)-[:KNOWS]-(a)
The pair (a, b) is always ordered by appearance even if not by semantics. So even if we remove the < or > symbol from the relationship declaration, the problem with the order of nodes in it cannot be eliminated. Therefore simply don't treat it is a problem.

Modeling recursive breakdown structures in graph database

For recursive breakdown structures, is it better to model as ...
a. Group HAS Subgroup... or
b. Subgroup PART_OF Group ?? ....
Some neo4j tutorials imply model both (the parent_of and child_of example) while the neo4j subtype tutorials imply that either will work fine (generally going with PART-OF).
Based on experience with neo4j, is there a practical reason for choosing one or the other or use both?
[UPDATED]
Representing the same logical relationship with a pair of relationships (having different types) in opposite directions is a very bad idea and a waste of time and resources. Neo4j can traverse a single relationship just as easily from either of its nodes.
With respect to which direction to pick (since we do not want both), see this answer to a related question.

Querying single relationship from a bidirectional relationship in Neo4j

Is it possible to show only one direction relationship from a bidirectional relationship?
(n)-[:EMAIL_LINK]->(m)
(n)<-[:EMAIL_LINK]-(m)
If the relationship type in question does not have directional semantics, it's best practice to have them only one time in the graph and omit the direction while querying, i.e. (a)-[:EMAIL_LINK]-(b) instead of (a)-[:EMAIL_LINK]->(b).
To get rid of duplicated relationships in different directions, use:
MATCH (a)-[r1:EMAIL_LINK]->(b)<-[r2:EMAIL_LINK]-(a)
WHERE ID(a)<ID(b)
DELETE r2
if your graph is large you need to take care of having reasonable transaction sizes by adding a LIMIT and running the query multiple times until all have been processed.
NB: the WHERE ID(a)<ID(b) is necessary. Otherwise a and b might change roles during in a later iteration. Consequently r1 and r2 would change roles as well and both get deleted.

Resources