Performance 在neo4j中使用FOREACH时删除关系

Performance 在neo4j中使用FOREACH时删除关系,performance,foreach,neo4j,Performance,Foreach,Neo4j,我需要删除在FOREACH上迭代的特定类型的节点的关系 详情如下: PROFILE MATCH (n:Label1)-[r1:REL1]-(a:Label2) WHERE a.prop1 = 2 WITH n 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

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

详情如下:

PROFILE MATCH (n:Label1)-[r1:REL1]-(a:Label2) 
WHERE a.prop1 = 2 
WITH n 
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
FOREACH (sub IN less_than_rows | 
  MERGE (sub)-[r:REL2]-(:Label2) 
  DELETE r 
  MERGE(l2:Label2{id:540}) 
  MERGE (sub)-[:APPEND_TO {s:0}]->(l2) 
  SET sub.prop3=1, sub.prop2=1484764200) 
WITH DISTINCT other_rows, count 
FOREACH (sub IN other_rows | 
  MERGE(l2:Label2{id:540}) 
  MERGE (sub)-[:APPEND_TO {s:0}]->(l2) 
  SET sub.prop3=sub.prop3+1)
RETURN count
配置文件匹配(n:Label1)-[r1:REL1](a:Label2)
其中a.prop1=2
与n
以COLLECT(n)作为行
其中[a在a.prop2<1484764200]小于_行的行中,
[b在b.prop2=1484764200和b.prop3<2的行中]与其他_行一样
以大小(小于等于行)+大小(其他行)作为计数,小于等于行,其他行
FOREACH(子行数小于
合并(sub)-[r:REL2]-(:Label2)
删除r
合并(l2:Label2{id:540})
合并(sub)-[:将_附加到{s:0}]->(l2)
设置sub.prop3=1,sub.prop2=1484764200)
对于不同的其他_行,计数
FOREACH(其他行中的子行)
合并(l2:Label2{id:540})
合并(sub)-[:将_附加到{s:0}]->(l2)
设置sub.prop3=sub.prop3+1)
返回计数
因为FOREACH不支持MATCH,所以我使用MERGE来实现它。但是当我执行它时,它非常慢(大约需要1分钟)。 但如果我在没有使用out FOREACH(停止向上推)的情况下超过,它将提供大约1秒的时间

问题::显然是FOREACH或in-FOREACH内部操作的问题。 我想删除一个特定关系,创建另一个关系,并将一些属性设置为node。


注意:我显示了total查询,因为有没有其他方法可以达到相同的要求(在这个FOREACH中,我尝试了CASE-WHEN)

代替FOREACH,您可以展开行集合并处理这些行。您还可以使用可选的匹配,而不是合并,这样可以避免在找不到匹配项时出现“合并”的回退创建行为。看看这两者的比较:

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
PROFILE
匹配(n:Label1)-[:REL1]-(a:Label2)
其中a.prop1=2
以COLLECT(n)作为行
其中[a在a.prop2<1484764200]小于_行的行中,
[b在b.prop2=1484764200和b.prop3<2的行中]与其他_行一样
以大小(小于等于行)+大小(其他行)作为计数,小于等于行,其他行
//在这里执行速度更快,只有一行,因此它执行一次
合并(l2:Label2{id:540})
将小于_的行作为子行展开
可选匹配(sub)-[r:REL2]-(:Label2)
删除r
合并(sub)-[:将_附加到{s:0}]->(l2)
设置sub.prop3=1,sub.prop2=1484764200
具有不同的其他_行、计数、l2
将其他_行作为子行展开
合并(sub)-[:将_附加到{s:0}]->(l2)
设置sub.prop3=sub.prop3+1
返回计数

我注意到您最初的查询有几点:

  • MERGE(l2:Label2{id:540})
    应该从两个
    FOREACH
    子句中移出,因为它只需要执行一次。这会减慢查询速度。事实上,如果您希望节点已经存在,可以使用
    匹配
  • MERGE(sub)-[:APPEND_TO{s:0}]->(l2)
    可能不会执行您想要的操作,因为它只会匹配
    s
    属性仍然为
    0
    的现有关系。如果
    s
    不是
    0
    ,则最终将创建一个附加关系。为确保存在单个关系并且其
    s
    值(重置为)
    0
    ,您应该从模式中删除
    {s:0}
    测试,并使用
    SET
    设置
    s
    值;这也会加快合并的速度,因为它不需要进行属性值测试
此版本的查询应该可以解决上述问题,并且速度更快(但您必须尝试一下,看看速度有多快):


cybersam在将l2的合并从循环中移出方面有一个很好的观点。尽管我的查询没有FOREACH,但我将其移到了展开上方,因此它只在一行上执行一次,而不是在展开后的每一行上执行一次。
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;
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;