让我们假设这个用例:
“在2013/05/12 20:00
到2013/05/14 21:00
之间获取所有已通过的事件。”
在Neo4j中实现这种情况的第一种方法是将属性编入索引:
事件(startAt:...,endAt:...)(startAt
和endAt
被编入索引)
这将导致扫描具有与实际查询相对应的属性的所有事件。
我刚读过的其他方式:
问题是:在这种情况下,节点遍历在性能方面要好于处理日期的索引属性吗?
答案 0 :(得分:5)
设计时间线树的更好方法(特别是在您想要在间隔时段之间搜索的情况下): here
如果您对在一个时间间隔之间发现一系列事件更感兴趣,Cypher遍历找到合适的事件会更好。
Neo4j将节点属性存储为链表。更多信息:here如果您浏览neo4j存储架构,您将意识到创建独特的关系类型将使您的遍历性能更加出色。
答案 1 :(得分:5)
在性能方面,节点遍历要比在这种情况下处理日期的索引属性好得多(在多级日期时间索引中)吗?
不,日期的索引属性比这种类型的数据结构的遍历更具性能。
以下是使用混合方法的详细示例。考虑以下子图,其中椭圆表示图中的连续模式。
请查看https://gist.github.com/kbastani/8519557获取或创建(合并)多级日期时间索引的完整日历Cypher脚本。此数据结构允许您从一个日期遍历到另一个日期,以获取时间序列的一系列事件。索引属性匹配和遍历的组合是最好的方法,并且在正确建模时具有高性能。
例如,请考虑以下Cypher查询:
// What staff have been on the floor for 80 minutes or more on a specific day?
WITH { day: 18, month: 1, year: 2014 } as dayMap
// The dayMap field acts as a parameter for this script
MATCH (day:Day { day: dayMap.day, month: dayMap.month, year: dayMap.year }),
(day)-[:FIRST|NEXT*]->(hours:Hour),
(hours)<-[:BEGINS]-(shift:Event),
(shift)<-[:WORKED]-(employee:Employee)
WITH shift, employee
ORDER BY shift.timestamp DESC
WITH employee, head(collect(shift)) as shift
MATCH (shift)<-[:CONTINUE*]-(shifts)
WITH employee.firstname as first_name,
employee.lastname as last_name,
SUM(shift.interval) as time_on_floor
// Only return results for staff on the floor more than 80 minutes
WHERE time_on_floor >= 80
RETURN first_name, last_name, time_on_floor
在这个查询中,我们询问数据库“在特定的一天,连续80分钟或更长时间内,有哪些工作人员在场?”将班次分成20分钟的连续间隔,指向系列中的下一个班次为CONTINUE或BREAK。
首先,您首先使用索引属性匹配日期。然后,通过遍历日期时间多级索引扫描连接事件的当天时间。然后反转事件的顺序以获取系列中的最新事件。然后遍历直到遇到“BREAK”关系。最后,应用time_on_floor大于或等于80分钟的条件。