Cypher查询优化:匹配时间

时间:2018-02-14 03:15:24

标签: neo4j cypher

我创建了一个Needham时间树(http://www.markhneedham.com/blog/2014/04/19/neo4j-cypher-creating-a-time-tree-down-to-the-day/),直到一小时。 在每个小时节点上我存储了纪元时间

CREATE (h:Hour {hour: hour, day:day, month: month, year:year, time: apoc.date.parse(year +"-"+month+"-"+day+" "+hour+":00", "s", "yyyy-MM-dd hh:mm")})

现在我想将该小时内发生的事件与小时节点相关联。我使用以下查询执行此操作:

//Create one example event node
create (e:Event {time: apoc.date.parse("2017-11-17 13:15", "s", "yyyy-mm-dd HH:mm")})
with e
match (h:Hour) where h.time <= e.time and (h.time+3600) > e.time
merge (e)-[:IN_HOUR]->(h)

我将事件时间和时间都编入索引。

这适用于小组事件但是当我将事件扩展到数十万个范围时,它会非常缓慢。 (按每小时几百到一千个关系的顺序)

我怎样才能更快地完成这项工作?

我试过了两次

match (e:Event) ...`

using load CSV迭代每个事件,将其与现有事件节点匹配,然后创建与时间树的关系。

`

2 个答案:

答案 0 :(得分:1)

[EDITED]

首先,在:Hour(time)上创建index

CREATE INDEX ON :Hour(time);

然后,将您的查询更改为以下内容(假设您将事件时间作为event_time parameter传递:

CREATE (e:Event {time: apoc.date.parse($event_time, "s", "yyyy-MM-dd HH:mm")})
WITH e
MATCH (h:Hour {time: e.time/3600*3600})
USING INDEX h:Hour(timer)
MERGE (e)-[:IN_HOUR]->(h);

表达式e.time/3600*3600e.time 向下舍入到最近的小时(但仍以秒为单位)。由于:Hour(time)已编入索引,因此MATCH应该很快。

注意:USING INDEX子句可以让Cypher Planner提示它应该利用索引。规划师不会这样做。如果您PROFILE查询,则可以查看是否需要提示。

您的查询无法使用索引,因为其WHERE子句太复杂了。

答案 1 :(得分:0)

以下是我登陆的解决方案: 感谢cybersam我意识到我的where子句太复杂了,无法使索引工作。不幸的是,cybersam的方法同样缓慢。我通过添加match属性(并将其编入索引)来更新(:Event)节点,从timeHour中删除了计算

match (e:Event) set e.timeHour = e.time/3600*3600

然后我可以通过以下方式在3秒内加入几十万关系:

match (e:Event)
match (h:Hour) where h.time = e.timeHour
merge (e)-[:IN_HOUR]->(h)