Alexander Petrov
Alexander Petrov

Reputation: 9492

How to express a time period (temporal) relationship in a graph database neo4j

Hi I have the the following relationship I would like to express in neo4j and I would like to find the optimal way, or maybe not the optimal but the different ways I can do that in a good way. The case is as follows:

The time period is a very important quality so in a way it is a first class citizen of the model. What I am wondering is, if I express this as Neo4J model there are several ways I can do this:

Aproach 1.

Aproach 2.

Then the relationship will look like. *Animal --FOR--> Period --Assigned-->CAGE

What questions the model should be capable of answering.

We should be able to collect information if Animals have every been placed together at the same time interval at the same cage. The thing is that One open space may contain many Cages so we would like to find out if two animals have ever been co-located within the same Open Space.

Upvotes: 3

Views: 815

Answers (1)

cybersam
cybersam

Reputation: 67019

Approach 2 is not practical if you have a unique (and therefore shared) Period node for each specific time period, since there could be any number of ASSIGNED relationships for that node, and you would not be able to tell which of those relationships belonged to which animal (without redundantly storing an animal ID in each relationship).

With Approach 1, let's assume this data model (where A represents: "an animal is assigned to a cage that is located in a space", and B represents: "an animal is assigned directly to a space -- not a cage"):

A. (:Animal)-[:ASSIGNED {start: 123, end: 789}]->(:Cage)-[:LOCATED_IN]->(:Space)
B. (:Animal)-[:ASSIGNED {start: 234, end: 777}]->(:Space)

To get info on all animals occupying the same cage at the same time:

MATCH
   (a1:Animal)-[r1:ASSIGNED]->(c:Cage),
   (a2:Animal)-[r2:ASSIGNED]->(c)
WHERE ID(a1) < ID(a2) AND r1.start < r2.end AND r2.start < r1.end
RETURN c, a1, r1, a2, r2

To get info on all animals occupying the same space at the same time:

MATCH
  (a1:Animal)-[r1:ASSIGNED]->()-[:LOCATED_IN*0..1]->(s:Space),
  (a2:Animal)-[r2:ASSIGNED]->()-[:LOCATED_IN*0..1]->(s)
WHERE ID(a1) < ID(a2) AND r1.start < r2.end AND r2.start < r1.end
RETURN s, a1, r1, a2, r2

NOTES:

  • The ID(a1) < ID(a2) test is for avoiding duplicate results (animals 1 and 2, and then again as 2 and 1).
  • The r1.start < r2.end AND r2.start < r1.end test is for detecting overlapping occupancy times.
  • The (x)-[:LOCATED_IN*0..1]->(y) syntax matches a variable-length path of either length 0 (in which case there is no LOCATED_IN relationship, and x is the same as y) or length 1.

Upvotes: 5

Related Questions