我需要删除在 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

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

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


注意::我显示了总查询,因为有没有其他方法可以实现相同的要求(在此 FOREACH 之外,我尝试使用 CASE WHEN)

最佳答案

我注意到有关您的原始查询的一些信息:

  • 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;
    

    关于performance - 在 Neo4j 中使用 FOREACH 时删除关系,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41743849/

    10-12 12:51
    查看更多