Ste*_*rig 7 graph neo4j cypher
鉴于我们有以下Neo4j架构(简化但它显示了重要的一点).有两种类型的节点NODE和VERSION.VERSIONs NODE通过VERSION_OF关系连接到s .VERSION节点确实有两个属性from和until这表示有效性时间跨度-一方或双方可以NULL(在Neo4j的条件不存在)表示无限.NODEs可以通过HAS_CHILD关系连接.同样,这些关系具有两个属性from和until这表示有效性时间跨度-一方或双方可以NULL(在Neo4j的条件不存在)表示无限.
编辑:VERSION节点和HAS_CHILD关系的有效日期是独立的(即使示例巧合地显示它们是对齐的).
该示例示出了两个NODE小号阿和乙.A有两个VERSIONs AV1直到6/30/17和AV2从7/1/17开始,而B只有一个版本BV1无限制.B通过关系连接到A,HAS_CHILD直到6/30/17.
现在的挑战是在一个特定时刻查询所有不是子节点(即根节点)的节点.鉴于上面的例子中,查询应该返回刚刚乙如果查询日期,例如17年6月1日,但它应该返回乙和一个如果查询日期如17年8月1日(因为一个是不是一个孩子B截至7/1/17更多).
今天的当前查询大致类似于那个:
MATCH (n1:NODE)
OPTIONAL MATCH (n1)<-[c]-(n2:NODE), (n2)<-[:VERSION_OF]-(nv2:ITEM_VERSION)
WHERE (c.from <= {date} <= c.until)
AND (nv2.from <= {date} <= nv2.until)
WITH n1 WHERE c IS NULL
MATCH (n1)<-[:VERSION_OF]-(nv1:ITEM_VERSION)
WHERE nv1.from <= {date} <= nv1.until
RETURN n1, nv1
ORDER BY toLower(nv1.title) ASC
SKIP 0 LIMIT 15
Run Code Online (Sandbox Code Playgroud)
这个查询通常工作得相对较好,但是当它用在大型数据集上时(与真实的生产数据集相比),它开始变慢.使用20-30k NODEs(大约是VERSIONs的两倍),(实际)查询在Mac OS X上运行的小型docker容器上大约需要500-700 ms),这是可以接受的.但是在1.5M NODEs(大约是VERSIONs的两倍)的情况下,(真实的)查询在裸机服务器上花费的时间超过1分钟(除了Neo4j之外别无其他).这不是真的可以接受.
我们可以选择调整此查询吗?是否有更好的方法来处理NODEs 的版本控制(我怀疑这里是性能问题)还是关系的有效性?我知道关系属性无法编入索引,因此可能有更好的模式来处理这些关系的有效性.
非常感谢任何帮助甚至是丝毫的暗示.
迈克尔·亨格回答后编辑:
根节点的百分比:
使用当前示例数据集(1.5M节点),结果集包含大约2k行.那不到1%.
ITEM_VERSION节点在第一个MATCH:
我们使用ITEM_VERSION nv2过滤器将结果集过滤到在给定日期ITEM没有连接其他ITEM节点的节点.这意味着要么不存在对于给定日期有效的关系,要么连接的项目不能具有ITEM_VERSION对给定日期有效的关系.我试图说明这一点:
// date 6/1/17
// n1 returned because relationship not valid
(nv1 ...)->(n1)-[X_HAS_CHILD ...6/30/17]->(n2)<-(nv2 ...)
// n1 not returned because relationship and connected item n2 valid
(nv1 ...)->(n1)-[X_HAS_CHILD ...]->(n2)<-(nv2 ...)
// n1 returned because connected item n2 not valid even though relationship is valid
(nv1 ...)->(n1)-[X_HAS_CHILD ...]->(n2)<-(nv2 ...6/30/17)
Run Code Online (Sandbox Code Playgroud)不使用关系类型:
这里的问题是该软件具有用户定义的模式,ITEM节点通过自定义关系类型连接.由于我们不能在一个关系上有多个类型/标签,这种关系的唯一共同特征是它们都是从它们开始的X_.这里没有简化的例子.会在type(r) STARTS WITH 'X_'这里搜索谓词帮助吗?
我认为改进的一个好的开始是使用索引来匹配节点,这样您就可以快速获得较小的相关节点子集进行搜索。您现在的方法必须每次都检查所有 :NODE 及其所有关系和模式,正如您所发现的,这不会随着您的数据而扩展。
现在,图表中唯一具有日期/时间属性的节点是 :ITEM_VERSION 节点,所以让我们从这些节点开始。您需要 :ITEM_VERSION 的 from 和 Until 属性的索引以进行快速查找。
空值会给您的查找带来问题,因为与空值的任何不等式都会返回空值,并且大多数处理空值的解决方法(使用 COALESCE() 或针对空值情况的多个 AND/OR)似乎会阻止使用索引查找,这就是我特别建议的重点。
我鼓励您将 from 和 Until 中的空值替换为最小值和最大值,这应该让您能够利用通过索引查找查找节点的优势:
MATCH (version:ITEM_VERSION)
WHERE version.from <= {date} <= version.until
MATCH (version)<-[:VERSION_OF]-(node:NODE)
...
Run Code Online (Sandbox Code Playgroud)
这至少应该在开始时提供对较小节点子集的快速访问,以便继续查询。