Reputation: 13
I need a bit of help. I have a graph. It's for project management app
The Day node is represented as follows. The Occupancy node has a START and an optional END relationship to the Day node and the Employee node has the OCCUPIES relationship to the Occupancy node. the Occupancy node has the OCCUPIES relationship to the Project node.
So my question is: get all the employees that occupied the project on a specific date.
The query that i have so far:
match (employee:Employee)-[:OCCUPIES]->(o:Occupancy)-[:OCCUPIES]->(project:Project{uuid:"ed409308-3202-495f-b834-ef1e8d5039d6"})
with employee, o
match(:Year{value:2018})-[:CONTAINS]->(:Month {value:10})-[:CONTAINS]->(day:Day {value:10})
with day, employee, o
match(o)-[:START]-(start:Day)-[:NEXT*0..365]->(day)
optional match(o)-[:END]-(end:Day)
optional match(day)-[:NEXT*0..300]->(end)
return employee
But that does not work. It gives me all the employees regardless if theirs occupancy ended before the date. Example in the graph above all the occupancies start on the 10.april.2018, half of them end on 1.june.2018. In the query i got the date 10.october.2018.
Can somebody help me with this?
regards Slavko
Upvotes: 0
Views: 72
Reputation: 13
Thank for your answers. It helped me allot. The query that i wrote based on your help:
match(:Year{value:{y}})-[:CONTAINS]->(:Month {value:{m}})-[:CONTAINS]->(day:Day {value:{d}})
with day
match (employee:Employee)-[:OCCUPIES]->(o:Occupancy)-[:OCCUPIES]->(project:Project{uuid:{project}})
with day, employee, project, o
match (o)-[:START]->(start:Day)
with day, employee, project, o, start
match p=shortestpath((start)-[:NEXT*0..365]->(day))
with day, employee, project, o, start, p
WHERE all(day IN NODES(p) WHERE NOT (o)-[:END]->(day))
optional match(employee)-[:WORKS]->(dayshift:Shift{shifttype:0})-[:WORKDAY]->(day)
optional match(dayshift)-[:WORKS]->(project)
optional match(employee)-[:WORKS]->(nightshift:Shift{shifttype:1})-[:WORKDAY]->(day)
optional match(nightshift)-[:WORKS]->(project)
return employee, dayshift, nightshift
But i have one more problem. If the Occupancy starts on lets say 1.april.2018 and ends 1.april.2018 so it was one day long. for this case the query above does not work because it has a END relationship.
Any suggestion how to solve that?
Upvotes: 0
Reputation: 67019
The following clause matches all occupancies that started up to a year before the desired start date (including the desired start date). This is probably why all employees were returned.
MATCH (o)-[:START]-(start:Day)-[:NEXT*0..365]->(day)
If you wanted to find occupancies that started on a specific day
, you should have used this:
MATCH (o)-[:START]-(day)
Or, if you actually wanted to find occupancies that started on a specific day
or within a year after that date, you should have used the following (I will assume this is what you wanted):
MATCH (o)-[:START]-(start:Day)<-[:NEXT*0..365]-(day)
Your OPTIONAL MATCH
clauses currently have no effect at all on whether an employee
is returned. (Also, those clauses only match end
dates that are within 300 days after the start day
-- I will assume this is a requirement of your use case even though it is not stated in your question.)
The following query tries to address both issues, and may work for you:
MATCH (employee:Employee)-[:OCCUPIES]->(o:Occupancy)-[:OCCUPIES]->(project:Project{uuid:"ed409308-3202-495f-b834-ef1e8d5039d6"})
MATCH (:Year{value:2018})-[:CONTAINS]->(:Month {value:10})-[:CONTAINS]->(day:Day {value:10})
MATCH (o)-[:START]-(start:Day)<-[:NEXT*0..365]-(day)
OPTIONAL MATCH (o)-[:END]-(end:Day)
OPTIONAL MATCH p=(day)-[:NEXT*0..300]->(end)
RETURN CASE WHEN p IS NULL THEN employee ELSE NULL END AS employee;
Note: All the NEXT
relationship hops needed, per candidate employee, to satisfy this query (up to 665) seem expensive. You may want to come up with a more efficient data model (but if you need help with that, it would require a new question).
Upvotes: 0
Reputation: 7478
Can you try this query :
MATCH
(:Year{value:2018})-[:CONTAINS]->(:Month {value:10})-[:CONTAINS]->(day:Day {value:10}),
(employee:Employee)-[:OCCUPIES]->(o:Occupancy),
(o)-[:OCCUPIES]->(project:Project{uuid:"ed409308-3202-495f-b834-ef1e8d5039d6"}),
(o)-[:START]->(start:Day),
p=shortestpath((start)-[:NEXT*]->(day))
WHERE all(day IN NODES(p) WHERE NOT (o)-[:END]->(day))
RETURN employee
The trick here is that I search the shortestpath between the starting day, and the day you give to the query. For each node on this path, I'm checking that is there is no END
relationship to the Occupation
.
So normally, you should only have Occupation
nodes you are searching.
Upvotes: 0