Lievcin
Lievcin

Reputation: 938

Managing history of a hierarchy in a graph database

I've been reading up on graph databases and neo4j in particular. I've been thinking of a project where a hierarchy of people would be represented using nodes and this seems like the ideal modelling choice.

But there's one caveat, and that is keeping history. It seems clear that if I work for someone, my node is related (like 'works for') to another node in the hierarchy. What if I didn't work for that person anymore and changed managers?

It seems obvious that the existing relationship could be destroyed and a new one created to the new manager, but if this was the case, then I would always would have a real time hierarchy with a view 'as it stands now'.

How would someone model having to keep somehow the history, that from one date to another I worked for someone, and from a certain date I work for someone else?

Thanks a lot for your help!

Upvotes: 2

Views: 602

Answers (1)

cybersam
cybersam

Reputation: 67019

Assuming that a person has only 1 job at a time, this data model may work for you.

(p:Person {id:123})-[:HISTORY]->
  (curr:Job {start: 999})-[:PRIOR_JOB]->
  (j1:Job {start: 888, end: 995})-[:PRIOR_JOB]->
  (j2:Job {start: 555, end: 888})-[:PRIOR_JOB]->
  (j3:Job {start: 123, end: 532})

(j1)-[:MANAGED_BY]->(:Person {id: 15})
(j2)-[:MANAGED_BY]->(:Person {id: 22})
(j3)-[:MANAGED_BY]->(:Person {id: 79})

When p starts working for a new manager, you'd just have to "insert" a new Job node (connected to the new manager) to the front of his/her history linked list:

MATCH (p:Person { id: { emp_id }})
OPTIONAL MATCH (p)-[oldHist:History]->(j1:Job)
WITH p, oldHist, COLLECT(j1) AS oldJob
CREATE (p)-[:HISTORY]->(j2:Job {start: { start_date }})-[:MANAGED_BY]->(m:Person { id: { mgr_id }})
FOREACH (j IN oldJob | 
         DELETE oldHist
         CREATE (j2)-[:PRIOR_JOB]->(j))

This query uses OPTIONAL MATCH to find the start of the history list, since it may not exist if this is the person's first job. Similarly, it uses a FOREACH trick to only attempt to fix up the history list if it existed before.

I assume that emp_id, start_date, and mgr_id are supplied as parameters. I also assume that the j1.end property is set in a prior query (but this query's FOREACH could be modified to set it as well).

Upvotes: 4

Related Questions