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



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

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

(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前开球。

试试这个:

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

这是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

我相信这是去年在Neo4j 3.0.3中解决的,正如本次提交中所看到的那样-https://github.com/neo4j/neo4j/commit/2c5c3dd

最新更新