neo4j中基于时间/日期的搜索

时间:2016-04-22 09:10:41

标签: neo4j cypher graph-databases

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

  • 如何在搜索从节点X到节点Y(RegEx?/ Wildcard?)的特定路径时限制关系/边缘?例如,所有边都有2个时间属性,"开始"和"结束"。我想在凌晨2点到凌晨3点之间找到节点之间的路径。?
  • 如何追踪时间路径?让我们说一辆车从A' A开始。到' B'这条路线需要一个小时,即从早上5点到早上6点。下一节,来自' B'到' C'从一个小时开始,但是从早上7点到早上8点,因为司机休息了一个小时。如何以仅允许逻辑上有效(时间)路径的方式查询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'发送包裹给cooworker' D'上午11点,但是cooworker将这个特殊的包转发给了cooworker' B'一个小时前。女巫是不可能的。

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

1 个答案:

答案 0 :(得分:1)

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

此查询应仅返回从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))