Neo4j Cypher:在链表中找到第一个匹配关系?

时间:2014-02-13 06:32:48

标签: neo4j cypher

就像问题所说的那样。 “第一”这个词很重要 - 可能会有更多符合相同条件的关系。

真实世界的用例:每个关系都有一个时间戳属性,我想找到在某个时间之前发生的第一个(例如“中午之前”)。 E.g:

(head) -[time: 9]-> () -[time: 8]-> () -[time: 7]-> ...

-

这就是我所拥有的(假设我们知道head节点是什么):

MATCH (head) -[prevs:next*0..]-> (x) -[rel:next]-> (y)
WHERE NONE(prev IN prevs WHERE prev.time < {time})
AND rel.time < {time}
RETURN x, rel, y

这就是说,“遍历一个或多个关系,直到我们在{time}之前找到一个,之前的关系都不在{time}之前。”

查询有效,但令人惊讶的是,即使在找到一个匹配项之后仍会继续遍历列表。更准确地说,它不断扩展可变长度匹配 - 即使NONE()检查在其余部分明显失败。

也许这只是Cypher的优化还未到来?与此同时,是否有更有效的方式来查询?(IOW,有没有什么方法可以在第一场比赛后实现“短路”?)

-

这是一个可以玩的控制台链接:

http://console.neo4j.org/r/b4v2tl

重要提示:设置会创建一个1001节点的链接列表,因此它可能会冻结您的浏览器/标签一分钟左右。我建议在解冻后立即禁用“Toggle Viz”。

此控制台示例还反转了上述示例中的时间顺序,只是为了简单起见。因此请将此查询粘贴到:

MATCH (head:Node {id: 0}) -[prevs:next*0..]-> (x) -[rel:next]-> (y)
WHERE NONE(prev IN prevs WHERE prev.time > 5)
AND rel.time > 5
RETURN x, rel, y

那是在查询列表中第五个关系应该是什么。

你会看到Neo4j拒绝执行查询。如果您将0..更改为例如0..10,它会起作用。继续碰撞10,你会发现它越来越慢。警卫按100开始。

3 个答案:

答案 0 :(得分:0)

试试这个:

MATCH (x)-[r:next]->(y) 
WHERE r.time > {time} 
RETURN x, r, y
ORDER BY r.time
LIMIT 1

修改

如果您的关系已按时间属性编入索引,则

START r=relationship:rels(time = {time})
MATCH (x)-[r1:next]->(y)-[r]->()
RETURN x,r1,y

答案 1 :(得分:0)

这是2.1之前的密码的缺点(希望能解决它)。

如果紧急,请查看一个非托管扩展,在几行java中执行此操作:

https://github.com/jexp/neo4j-activity-stream

https://github.com/jexp/neo4j-activity-stream/blob/master/src/main/java/org/neo4j/example/activity/ActivityStream.java#L59

答案 2 :(得分:0)

我相信去年在Neo4j 3.0.3中解决了这个问题,如本次提交所示 - https://github.com/neo4j/neo4j/commit/2c5c3dd