You can use shortestPath
for this and it will be much faster. In general, you should never use [:REL_TYPE*]
because it does an exhaustive search for every path of any length between the nodes.
I created your data:
CREATE (:User {id:1})-[:PREV]->(:Event {id:1, date:1450806880004, done:false})-[:PREV]->(:Event {id:2, date:1450806880003, done:false})-[:PREV]->(:Event {id:3, date:1450806880002, done:true})-[:PREV]->(:Event {id:4, date:1450806880002, done:true});
Then, the following query will find all previous Event nodes in a particular User's linked list where done=false and the date is less than or equal to, say, 1450806880005.
MATCH p = shortestPath((u:User)-[:PREV*]->(e:Event))
WHERE u.id = 1 AND
e.done = FALSE AND
e.date <= 1450806880005
RETURN p;
This yields:
p
[(6:User {id:1}), (6)-[6:PREV]->(7), (7:Event {date:1450806880004, done:false, id:1})]
[(6:User {id:1}), (6)-[6:PREV]->(7), (7:Event {date:1450806880004, done:false, id:1}), (7)-[7:PREV]->(8), (8:Event {date:1450806880003, done:false, id:2})]
So you can see it's returning two paths, one that terminates at Event with id=1 and another that terminates at Event with id=2.
Then you can do something like this:
MATCH p = shortestPath((u:User)-[:PREV*]->(e:Event))
WHERE u.id = 1 AND e.done = FALSE AND e.date <= 1450806880005
FOREACH (event IN TAIL(NODES(p)) | SET event.done = TRUE)
RETURN p;
I'm using TAIL here because it grabs all the nodes except for the first one (since we don't want to update this property for the User node). Now all of the done properties have been updated on the Event nodes:
p
[(6:User {id:1}), (6)-[6:PREV]->(7), (7:Event {date:1450806880004, done:true, id:1})]
[(6:User {id:1}), (6)-[6:PREV]->(7), (7:Event {date:1450806880004, done:true, id:1}), (7)-[7:PREV]->(8), (8:Event {date:1450806880003, done:true, id:2})]
EDIT: And don't forget the super fun bug where the shortestPath
function silently sets the maximum hop limit to 15 in Neo4j < 2.3.0. See
ShortestPath doesn't find any path without max hops limit
Find all events between 2 dates
So if you're on Neo4j < 2.3.0, you'll want to do:
MATCH p = shortestPath((u:User)-[:PREV*..1000000000]->(e:Event))
WHERE u.id = 1 AND e.done = FALSE AND e.date <= 1450806880005
FOREACH (event IN TAIL(NODES(p)) | SET event.done = TRUE)
RETURN p;