3

How do you decide the verb-direction of a relation ?

E.g I have a Country falling under a Sub REgion which in turn is under a Region. Which one would be better and are there any thumb rules on deciding the direction.

(Region)-[HAS]->(Sub Region)-[HAS]->(Country)

or

(Region)<-[BELONGS_TO]-(Sub Region)<-[BELONGS_TO]-(Country)

Regards San

Santo
  • 31
  • 2
  • 1
    This is almost a purely subjective question, I could see this question getting closed down for that. What it comes down to is whatever makes the most sense for your domain, and fits whatever level of vagueness or specificity you desire for your modeling. As Neo4j is flexible, there's no reason you can't just try out one way for awhile, and if you feel the other way is better, use APOC Procedures refactoring calls to change the relationship type and/or direction. – InverseFalcon Nov 10 '16 at 16:10
  • It really comes down to what does this direction mean. When you say country Falling under a SubRegion, can the SubRegion fall under a country ? If this is the case then a direction may make sense. If not then don't use a direction at all since it isn't a possible scenario. Avoiding directions is a good practice since it eliminates a great deal of complexity in your queries. You can move the semantics to the edge labels as well. – Alaa Mahmoud Nov 10 '16 at 23:29

1 Answers1

5

I agree with @InverFalcon that directionality is mostly a subjective decision. However, there may be (at least) one situation in which you might want to use a specific direction, especially if that will make an important use case faster.

This is related to the fact that often if you can make a Cypher pattern less specific (without affecting the output), then neo4j would have to do less work and your query would be faster.

For example, suppose your entire data model consists of 2 node labels and 2 relationship types, like below. (I use my own data model, since I don't know what your uses cases are.)

(:Person)-[:ACTED_IN]->(:Movie)
(:Person)-[:DIRECTED]->(:Movie)

In order to find the movies that an actor acted in, your query would have to look something like the following. (Notice that we have to specify the ACTED_IN type, because an outgoing relationship could also be of type DIRECTED. This means that neo4j has to explicitly test every outgoing relationship for its type):

MATCH (:Person {id: 123})-[:ACTED_IN]->(m:Movie)
RETURN m;

However, if your data model replaced the DIRECTED type with a DIRECTED_BY type that had opposite directionality, then it would look like this instead:

(:Person)-[:ACTED_IN]->(:Movie)
(:Person)<-[:DIRECTED_BY]-(:Movie)

With that tweak, your query could be simpler and faster (since neo4j would not have to test relationship types):

MATCH (:Person {id: 123})-->(m:Movie)
RETURN m;

And to be complete, notice that in the above 2 MATCH patterns we could actually remove the :Movie label, since in both data models the ACTED_IN end node will always have the Movie label.

cybersam
  • 63,203
  • 6
  • 53
  • 76
  • 1
    just for completeness of the answer; the Person label should not be removed, or else Neo4j will search all nodes for the id: 123 . Removing the label only speeds up things in the exact case above - MATCH (:Person {id: 123})-->(m:Movie) RETURN m; – Mihai Raulea Nov 15 '16 at 15:24