在neo4j中使用FOREACH时删除关系

时间:2017-01-19 14:10:40

标签: performance foreach neo4j

我需要删除迭代FOREACH的节点的特定类型的关系。

详细::

--sysroot

由于FOREACH不支持MATCH,我使用MERGE来实现它。但是当我执行它时它很慢(大约需要1分钟)。 但是,如果我超越FOREACH(停止更新),它会给出大约1秒的时间。

问题::显然FOREACH或FOREACH中的内部操作存在问题。 我想删除一个特定的关系,创建另一个关系并将一些属性设置为节点。

注意::我显示了总查询,因为有没有其他方法可以达到相同的要求(在此之前,我尝试过CASE WHEN)

2 个答案:

答案 0 :(得分:2)

我注意到了一些关于原始查询的内容:

  • MERGE(l2:Label2 {id:540})应该从两个FOREACH子句中删除,因为它只需要执行一次。这会降低查询速度。实际上,如果您希望节点已经存在,则可以改为使用MATCH
  • MERGE (sub)-[:APPEND_TO {s:0}]->(l2)可能无法达到预期效果,因为它只会匹配s属性仍为0的现有关系。如果s不是0,您最终会创建一个额外的关系。为确保存在单一关系且其s值为(重置为)0,您应从模式中删除{s:0}测试并使用SET进行设置s值;这也应该加快MERGE,因为它不需要进行属性值测试。

此版本的查询应该可以解决上述问题,并且速度更快(但您必须尝试一下才能看到更快):

PROFILE
MATCH (n:Label1)-[:REL1]-(a:Label2)
WHERE a.prop1 = 2
WITH COLLECT(n) AS rows
WITH
  [a IN rows WHERE a.prop2 < 1484764200] AS less_than_rows, 
  [b IN rows WHERE b.prop2 = 1484764200 AND b.prop3 < 2] AS other_rows 
WITH size(less_than_rows) + size(other_rows) AS count, less_than_rows, other_rows
MERGE(l2:Label2 {id:540}) 
FOREACH (sub IN less_than_rows | 
  MERGE (sub)-[r:REL2]-(:Label2) 
  DELETE r 
  MERGE (sub)-[r2:APPEND_TO]->(l2)
  SET r2.s = 0, sub.prop3 = 1, sub.prop2 = 1484764200) 
WITH DISTINCT l2, other_rows, count 
FOREACH (sub IN other_rows | 
  MERGE (sub)-[r3:APPEND_TO]->(l2) 
  SET r3.s = 0, sub.prop3 = sub.prop3+1)
RETURN count;

如果您只想在创建s关系时将APPEND_TO值设置为0,则使用ON CREATE子句而不是SET

PROFILE
MATCH (n:Label1)-[:REL1]-(a:Label2)
WHERE a.prop1 = 2
WITH COLLECT(n) AS rows
WITH
  [a IN rows WHERE a.prop2 < 1484764200] AS less_than_rows, 
  [b IN rows WHERE b.prop2 = 1484764200 AND b.prop3 < 2] AS other_rows 
WITH size(less_than_rows) + size(other_rows) AS count, less_than_rows, other_rows
MERGE(l2:Label2 {id:540}) 
FOREACH (sub IN less_than_rows | 
  MERGE (sub)-[r:REL2]-(:Label2) 
  DELETE r 
  MERGE (sub)-[r2:APPEND_TO]->(l2)
  ON CREATE SET r2.s = 0
  SET sub.prop3 = 1, sub.prop2 = 1484764200) 
WITH DISTINCT l2, other_rows, count 
FOREACH (sub IN other_rows | 
  MERGE (sub)-[r3:APPEND_TO]->(l2)
  ON CREATE r3.s = 0
  SET sub.prop3 = sub.prop3+1)
RETURN count;

答案 1 :(得分:0)

您可以UNWIND行集合并处理这些行,而不是FOREACH。您还可以使用OPTIONAL MATCH而不是MERGE,这样可以避免在找不到匹配项时MERGE的回退创建行为。看看这是如何比较的:

PROFILE 
MATCH (n:Label1)-[:REL1]-(a:Label2) 
WHERE a.prop1 = 2 
WITH COLLECT(n) AS rows 
WITH [a IN rows WHERE a.prop2 < 1484764200] AS less_than_rows, 
[b IN rows WHERE b.prop2 = 1484764200 AND b.prop3 < 2] AS other_rows 
WITH size(less_than_rows) + size(other_rows) AS count, less_than_rows, other_rows
// faster to do it here, only 1 row so it executes once
MERGE(l2:Label2{id:540}) 
UNWIND less_than_rows as sub
OPTIONAL MATCH (sub)-[r:REL2]-(:Label2) 
DELETE r 
MERGE (sub)-[:APPEND_TO {s:0}]->(l2) 
SET sub.prop3=1, sub.prop2=1484764200
WITH DISTINCT other_rows, count, l2
UNWIND other_rows as sub
MERGE (sub)-[:APPEND_TO {s:0}]->(l2) 
SET sub.prop3=sub.prop3+1
RETURN count