链接列表查询耗时太长

时间:2015-12-23 12:57:02

标签: neo4j cypher

我使用neo4j构建了一个链表模型。这里有一个代表:

Linked list of events

用户的列表为Events,每个人都有两个属性:datedone。在给定特定时间的情况下,我希望将之前的所有事件done属性设置为true

我目前的查询是:

MATCH (user:User {id: {myId} })-[rel:PREV*]->(event:Event {done:false}) 
WHERE event.date <= {eventTime}
SET event.done = true;

当列表有500个事件时,此查询需要12秒,我想让它更快。一种可能性是在查找已经完成的事件后停止查询,但我不知道该怎么做。

2 个答案:

答案 0 :(得分:1)

您的问题与性能问题和目标相当模糊,但性能的一个关键因素是在您正在检查的属性上创建索引。在您的情况下,这意味着在done属性和date属性上创建索引:

CREATE INDEX ON :Event(done)
CREATE INDEX ON :Event(date)

此外,您的查询会在用户的整个历史记录中检索所有事件,如下所示:

-[rel:PREV*]->

你可以限制深度,例如

-[rel:PREV*..20]->

防止完全遍历。这可能不会给你你正在寻找的结果,但是如果你的链表中有极端数量的节点,它会阻止长时间运行的查询(你没有指明该列表有多大,所以我没有这个想法是否真的有帮助。)

答案 1 :(得分:1)

您可以使用shortestPath进行此操作,速度会快得多。通常,您永远不应该使用[:REL_TYPE*],因为它会在节点之间对 任何长度的路径进行详尽的搜索。

我创建了你的数据:

CREATE (:User {id:1})-[:PREV]->(:Event {id:1, date:1450806880004, done:false})-[:PREV]->(:Event {id:2, date:1450806880003, done:false})-[:PREV]->(:Event {id:3, date:1450806880002, done:true})-[:PREV]->(:Event {id:4, date:1450806880002, done:true});

然后,以下查询将查找特定用户链接列表中所有先前的事件节点,其中done = false且日期小于或等于,例如1450806880005。

MATCH p = shortestPath((u:User)-[:PREV*]->(e:Event))
WHERE u.id = 1 AND 
      e.done = FALSE AND 
      e.date <= 1450806880005
RETURN p;

这会产生:

p
[(6:User {id:1}), (6)-[6:PREV]->(7), (7:Event {date:1450806880004, done:false, id:1})]
[(6:User {id:1}), (6)-[6:PREV]->(7), (7:Event {date:1450806880004, done:false, id:1}), (7)-[7:PREV]->(8), (8:Event {date:1450806880003, done:false, id:2})]

所以你可以看到它返回两个路径,一个终止于id = 1的Event,另一个终止于id = 2的Event。

然后你可以这样做:

MATCH p = shortestPath((u:User)-[:PREV*]->(e:Event))
WHERE u.id = 1 AND e.done = FALSE AND e.date <= 1450806880005
FOREACH (event IN TAIL(NODES(p)) | SET event.done = TRUE)
RETURN p;

我在这里使用TAIL因为它抓取了除第一个节点之外的所有节点(因为我们不想为User节点更新此属性)。现在,所有已完成的属性都已在Event节点上更新:

p
[(6:User {id:1}), (6)-[6:PREV]->(7), (7:Event {date:1450806880004, done:true, id:1})]
[(6:User {id:1}), (6)-[6:PREV]->(7), (7:Event {date:1450806880004, done:true, id:1}), (7)-[7:PREV]->(8), (8:Event {date:1450806880003, done:true, id:2})]

编辑:并且不要忘记超级有趣的错误,其中shortestPath函数在Neo4j中以无声方式将最大跳跃限制设置为15&lt; 2.3.0。见

ShortestPath doesn't find any path without max hops limit

Find all events between 2 dates

所以如果你在Neo4j&lt; 2.3.0,你想做的事:

MATCH p = shortestPath((u:User)-[:PREV*..1000000000]->(e:Event))
WHERE u.id = 1 AND e.done = FALSE AND e.date <= 1450806880005
FOREACH (event IN TAIL(NODES(p)) | SET event.done = TRUE)
RETURN p;