Time/date 基于 neo4j 的搜索

Time/date based searches in neo4j

在玩 neo4j 时出现了几个问题。目前有 2 个:

(Prague) -[:DISTANCE {begin: '5 am', end: '6 am'}]->(Brno), (Brno) -[:DISTANCE {begin: '7 am', end: '9 am'}]->(Liberec)

而这个无效:

(Prague) -[:DISTANCE {begin: '5 am', end: '6 am'}]->(Brno), (Brno) -[:DISTANCE {begin: '4 am', end: '6 am'}]->(Liberec)

再举个例子,给出的是下图:

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))

我正在寻找从节点 'A' 到节点 'B' 的路径。忽略约束 "start_time",我们在此图中有 3 条可能的路径:

在我们只考虑约束"start_time"的情况下,剩下两条路径:

因为路径'A' --> 'D' --> 'B'无效。在这种情况下,年表是错误的。 Cooworker 'A' 在上午 11 点向 cooworker 'D' 发送了一个包裹,但 cooworker 在一个小时前将这个特定包裹转发给了 cooworker 'B'。 不可能。

PS: 是否有工具可以生成具有边缘的节点作为 ASCII 艺术 resp。对于控制台? :)

首先,我建议您使用数字时间值而不是字符串。这将使 Cypher 变得更加简单和高效。此外,实际上,路径可以跨越多天,因此仅提供一天中的某个时间会导致错误的结果。例如,您可能想使用 epoch time。在我的回答中,我假设时间是数字。

此查询应该只有 return 个从 A 到 B 的有效路径:

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;

REDUCE 子句负责检查候选路径中的开始时间是否有意义。

您可以使用此数据检查结果(使用简单的数字时间值,但纪元时间也可以):

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))