问题
while playing around with neo4j a couple of questions arisen. At present time there are 2 of them:
- How can I limit the relationships/edges while searching for a specific path from node X to node Y (RegEx?/Wildcard?)? For instance all edges have 2 time attributes, "begin" and "end". I would like to find a path between nodes which occured between 2 am and 3 am in the morning.?
- How can track a time path? Lets say a car drove from 'A' to 'B'. The route took one hour, namely from 5 am to 6 am. The next section, from 'B' to 'C' took as well one hour but from 7 am to 8 am because the driver took a one hour rest. How can I query neo4j in the way that only logically valid (time) paths are allowed. For instance this should be valid:
(Prague) -[:DISTANCE {begin: '5 am', end: '6 am'}]->(Brno), (Brno) -[:DISTANCE {begin: '7 am', end: '9 am'}]->(Liberec)
whereas this one shall be invalid:
(Prague) -[:DISTANCE {begin: '5 am', end: '6 am'}]->(Brno), (Brno) -[:DISTANCE {begin: '4 am', end: '6 am'}]->(Liberec)
Another example, given is the following graph:
CREATE (a:BoxingMachine {title: 'A'})
CREATE (b:BoxingMachine {title: 'B'})
CREATE (c:BoxingMachine {title: 'C'})
CREATE (d:BoxingMachine {title: 'D'})
CREATE ((a)-[:FORWARDED {start_time: '9:00 am'}]->(b))
CREATE ((a)-[:FORWARDED {start_time: '7:00 am'}]->(c))
CREATE ((c)-[:FORWARDED {start_time: '8:00 am'}]->(b))
CREATE ((a)-[:FORWARDED {start_time: '11:00 am'}]->(d))
CREATE ((d)-[:FORWARDED {start_time: '10:00 am'}]->(b))
I am looking for paths from node 'A' to node 'B'. Ignoring the constraint "start_time", we have 3 possible paths in this graph:
'A' --> 'B'
'A' --> 'C' --> 'B'
'A' --> 'D' --> 'B'
In the case we consider the constraint "start_time" only, two paths left:
'A' --> 'B'
'A' --> 'C' --> 'B'
because the path 'A' --> 'D' --> 'B'
is invalid. In this case the chronology is wrong. Cooworker 'A' send a package to cooworker 'D' at 11am but cooworker forwarded this particular package to cooworker 'B' a hour earlier. Witch is impossible.
PS: Is there a tool to generate the nodes with there edges as ASCII art resp. for the console? :)
回答1:
First, I would advise that you use a numeric time value instead of a string. It would make the Cypher a lot simpler and efficient. Also, practically speaking, paths can span multiple days, so just providing a time of day will lead to wrong results. For instance, you may want to use epoch time. In my answer, I assume that the times are numeric.
This query should only return paths from A to B that are valid:
MATCH p=(a:BoxingMachine{title: 'A'})-[:FORWARDED*]->(b:BoxingMachine{title: 'B'})
WITH p, RELATIONSHIPS(p) AS rels
WHERE REDUCE(s = true, i IN RANGE(1, SIZE(rels)-1) |
CASE WHEN (rels[i]).start_time > (rels[i-1]).start_time
THEN s
ELSE false END)
RETURN p;
The REDUCE
clause is responsible for checking that the start times in a candidate path make sense.
You can check the results using this data (with simple numeric time values, but epoch time would also work):
CREATE (a:BoxingMachine {title: 'A'})
CREATE (b:BoxingMachine {title: 'B'})
CREATE (c:BoxingMachine {title: 'C'})
CREATE (d:BoxingMachine {title: 'D'})
CREATE ((a)-[:FORWARDED {start_time: 9}]->(b))
CREATE ((a)-[:FORWARDED {start_time: 7}]->(c))
CREATE ((c)-[:FORWARDED {start_time: 8}]->(b))
CREATE ((a)-[:FORWARDED {start_time: 11}]->(d))
CREATE ((d)-[:FORWARDED {start_time: 10}]->(b))
来源:https://stackoverflow.com/questions/36789608/time-date-based-searches-in-neo4j