就像问题所说的那样。"第一"这个词很重要——可能有更多的关系符合相同的条件。
真实世界用例:每个关系都有一个时间戳属性,我想找到在某个时间之前发生的第一个(例如"中午之前")。例如:
(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