Neo4j / Indexed属性VS创建不同的节点

时间:2014-01-22 12:53:12

标签: neo4j cypher graph-databases

让我们假设这个用例:

“在2013/05/12 20:002013/05/14 21:00之间获取所有已通过的事件。”

在Neo4j中实现这种情况的第一种方法是将属性编入索引:
事件(startAt:...,endAt:...)startAtendAt被编入索引)

这将导致扫描具有与实际查询相对应的属性的所有事件。

我刚读过的其他方式:

enter image description here

问题是:在这种情况下,节点遍历在性能方面要好于处理日期的索引属性吗?

2 个答案:

答案 0 :(得分:5)

设计时间线树的更好方法(特别是在您想要在间隔时段之间搜索的情况下): here

如果您对在一个时间间隔之间发现一系列事件更感兴趣,Cypher遍历找到合适的事件会更好。

Neo4j将节点属性存储为链表。更多信息:here如果您浏览neo4j存储架构,您将意识到创建独特的关系类型将使您的遍历性能更加出色。

答案 1 :(得分:5)

  

在性能方面,节点遍历要比在这种情况下处理日期的索引属性好得多(在多级日期时间索引中)吗?

不,日期的索引属性比这种类型的数据结构的遍历更具性能。

以下是使用混合方法的详细示例。考虑以下子图,其中椭圆表示图中的连续模式。

Multilevel Calendar Index

请查看https://gist.github.com/kbastani/8519557获取或创建(合并)多级日期时间索引的完整日历Cypher脚本。此数据结构允许您从一个日期遍历到另一个日期,以获取时间序列的一系列事件。索引属性匹配和遍历的组合是最好的方法,并且在正确建模时具有高性能。

Example Data Model for Time

例如,请考虑以下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分钟的条件。