Reputation: 938
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
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