Neo4j 执行缓慢的cypher查询,该查询创建节点以按属性值对现有节点进行分组

Neo4j 执行缓慢的cypher查询,该查询创建节点以按属性值对现有节点进行分组,neo4j,cypher,spring-data-neo4j,Neo4j,Cypher,Spring Data Neo4j,我有一个修改密码查询的性能问题。给定的是一个与子节点有大量传出关系的源节点。这些子节点都有一个键属性。现在的目标是在源节点和子节点之间创建新节点,以对共享相同键属性值的所有子节点进行分组。可以在neo4j控制台上找到该想法的示意图: 我将查询与spring-data-neo4j 2.2.2.RELEASE和neo4j 1.9.2 embedded一起使用。该查询的参数必须是节点id,并且该查询的结果应该是修改后的根节点 查询当前看起来像(比链接的neo4j控制台中的查询复杂一点): 属性自定义组

我有一个修改密码查询的性能问题。给定的是一个与子节点有大量传出关系的源节点。这些子节点都有一个键属性。现在的目标是在源节点和子节点之间创建新节点,以对共享相同键属性值的所有子节点进行分组。可以在neo4j控制台上找到该想法的示意图:

我将查询与spring-data-neo4j 2.2.2.RELEASE和neo4j 1.9.2 embedded一起使用。该查询的参数必须是节点id,并且该查询的结果应该是修改后的根节点

查询当前看起来像(比链接的neo4j控制台中的查询复杂一点):

属性自定义组是分组依据的键。在SDN中,它由DynamicProperties对象表示。我将其注释为索引,以及创建的组节点的groupingKey和origin属性

对于5000个子节点,将其分组需要约50秒。对于10000个节点~90秒。20000个节点~380秒,30000个节点>50分钟!对我来说,这看起来像一个o(对数n)刻度。但我的目标是o(n)规模,并在30分钟内处理500000多个子节点。我假设该查询的createunique部分导致了这个问题,因为对于新的组节点,它总是需要检查已经创建了什么类型的组节点。要检查的数量随着已经分组的子节点数量的增加而增加


有人知道如何更快地进行此查询吗?或者使用其他查询更快地执行相同的操作?

如果创建唯一性确实是问题所在,那么这将首先创建组,然后映射到它们

START root=node(*)
MATCH (root)-[r:LEAF]->(child) 
WHERE HAS (root.key) AND root.key='root' 
WITH DISTINCT child.key AS groupingKey, root as origin
CREATE UNIQUE (origin)-[:GROUP]->(intermediate { key:groupingKey,origin:ID(origin)})
WITH groupingKey, origin, intermediate
MATCH (origin)-[r:LEAF]->(leaf)
WHERE leaf.key = groupingKey
DELETE r
CREATE (intermediate)-[:LEAF]->(leaf)
RETURN DISTINCT origin
由于某种原因,控制台不允许我查看任何一个查询的执行计划,因此我不确定它是否有帮助

你也可以考虑索引根,这样你就不必在所有节点上做一个“WHW”了。您可以只检查key=root的索引

编辑上述查询的替代方法如下所示,这将避免使用collect再次匹配叶节点

START root=node(*)
MATCH (root)-[r:LEAF]->(child) 
WHERE HAS (root.key) AND root.key='root'
DELETE r 
WITH DISTINCT child.key AS groupingKey, root as origin, COLLECT(child) as children
CREATE UNIQUE (origin)-[:GROUP]->(intermediate { key:groupingKey,origin:ID(origin)})
WITH groupingKey, origin, intermediate, children
FOREACH(leaf IN children : CREATE (intermediate)-[:LEAF]->(leaf))
RETURN DISTINCT origin

好吧,现在我转向不在如此大的数据量上使用这种密码查询。我使用traversal API实现了相同的功能,用于提取可分组项,并使用
Neo4jTemplate
创建新节点和关系。现在50000个项目可以在5474ms中分组,而不是使用以前使用的cypher查询进行~1h。这是一个很大的改进。

谢谢分享您的想法。我刚刚测试了你的问题。事实证明,对5000个节点进行分组的速度实际上比我原来的慢2.6倍。这可能是因为其中还有一个不同的关键字。顺便说一下,我上周也尝试使用PROFILE关键字来获取执行计划。但由于一些交易问题而没有成功。我提出了另一个具体问题:谢谢分享。我只是想说,这个查询似乎导致了非最佳查询计划,因此您应该找到较低级别的解决方法:)
START root=node(*)
MATCH (root)-[r:LEAF]->(child) 
WHERE HAS (root.key) AND root.key='root'
DELETE r 
WITH DISTINCT child.key AS groupingKey, root as origin, COLLECT(child) as children
CREATE UNIQUE (origin)-[:GROUP]->(intermediate { key:groupingKey,origin:ID(origin)})
WITH groupingKey, origin, intermediate, children
FOREACH(leaf IN children : CREATE (intermediate)-[:LEAF]->(leaf))
RETURN DISTINCT origin