Time/date 基于 neo4j 的搜索
Time/date based searches in neo4j
在玩 neo4j 时出现了几个问题。目前有 2 个:
- 如何在搜索从节点 X 到节点 Y 的特定路径(正则表达式?/通配符?)时限制 relationships/edges?例如,所有边都有 2 个时间属性,"begin" 和 "end"。我想找到凌晨 2 点到 3 点之间发生的节点之间的路径。?
- 如何追踪时间路径?假设一辆汽车从 'A' 开到 'B'。这条路线用了一个小时,即从早上 5 点到早上 6 点。下一节,从 'B' 到 'C' 也花了一个小时,但是从早上 7 点到早上 8 点,因为 driver 休息了一个小时。如何以只允许逻辑有效(时间)路径的方式查询 neo4j。例如,这应该是有效的:
(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 条可能的路径:
'A' --> 'B'
'A' --> 'C' --> 'B'
'A' --> 'D' --> 'B'
在我们只考虑约束"start_time"的情况下,剩下两条路径:
'A' --> 'B'
'A' --> 'C' --> 'B'
因为路径'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))
在玩 neo4j 时出现了几个问题。目前有 2 个:
- 如何在搜索从节点 X 到节点 Y 的特定路径(正则表达式?/通配符?)时限制 relationships/edges?例如,所有边都有 2 个时间属性,"begin" 和 "end"。我想找到凌晨 2 点到 3 点之间发生的节点之间的路径。?
- 如何追踪时间路径?假设一辆汽车从 'A' 开到 'B'。这条路线用了一个小时,即从早上 5 点到早上 6 点。下一节,从 'B' 到 'C' 也花了一个小时,但是从早上 7 点到早上 8 点,因为 driver 休息了一个小时。如何以只允许逻辑有效(时间)路径的方式查询 neo4j。例如,这应该是有效的:
(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 条可能的路径:
'A' --> 'B'
'A' --> 'C' --> 'B'
'A' --> 'D' --> 'B'
在我们只考虑约束"start_time"的情况下,剩下两条路径:
'A' --> 'B'
'A' --> 'C' --> 'B'
因为路径'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))