Neo4j: one-directional / two-directional relationships

neo4jnosqlrelationship

So I looked into neo4j, and I may be using it in an upcoming project since its data model might fit my project very well. I looked through the docs but I still need an answer to this question:

Can I set relationships to be one-directional?

It seems that the neo4j people like movies so let's continue with that. If I have a graph like this:

Actor A -> [:Acts in] -> Movie B

then direction is obvious, because the nodes are different types.

But I like horror movies so…

Person A -> [:wants_to_kill] -> Person B

I need this relationship to be one-directional so if I query "Who does Person A want to kill?" I get Person B, if I query "Who does Person B want to kill?" I get nothing.

Sometimes I still need relationships to be two directional

Like:

Person A <-[:has_met] -> Person B

…which is obvious.

documentation says:

Relationships are equally well traversed in either direction. This means that there is
no need to add duplicate relationships in the opposite direction (with regard to 
traversal or performance).

While relationships always have a direction, you can ignore the direction where it is 
not useful in your application.

So docs say, relationships by default have an direction and I can ignore that if I wish.

Now this is where things get complicated:

Consider the following graph (and note the arrows)

Person A <- [:wants_to_kill] -> Person B
Person B -> [:wants_to_kill] -> Person C
Person C -> [:wants_to_kill] -> Person A

If I ignore the Directions for all [:wants_to_kill] I get false results
for "Who does Person A / C want to kill?"
If I knew which ones I had to ignore, I would not do the query.

So can I somehow set relationships to be two-directional (when creating them), or should I model this with two relationships (between Person A & B)?

Best Answer

A relationship in Neo4j always has a direction. If a relationship type's semantics do not incorporate a direction, e.g. has_met from your example, then it's best practice to apply an arbitrary direction on creation of the relationship. Querying is then done by using the "both directions" (there is no "larger/smaller than" character) notation in cypher:

start ... match (a)-[:HAS_MET]-(b) ....

In contrast, if the semantics of a relationship do have a direction like your wants_to_kill, you need to use two relationship to indicate that a and b wants kill the other one and vice versa. For the example above, you need to have 4 relationships:

Person A -[:wants_to_kill]-> Person B
Person B -[:wants_to_kill]-> Person A
Person B -[:wants_to_kill]-> Person C
Person C -[:wants_to_kill]-> Person A

To find all the person that A wants to kill you do:

start a=node:node_auto_index(name='A') match a-[:wants_to_kill]->victims_of_a return victims_of_a

To find all persons who want to kill A:

start a=node:node_auto_index(name='A') match murderer_of_a-[:wants_to_kill]->a return murderer_of_a
Related Topic