我目前正在编写一个猫鼬插件,以使用javascript neo4j driver自动维护neo4j节点,并且目前正在将更新更新(保存部分工作于atm)映射到密码查询。
我目前停留在用例上,我想更新文档(一个:Class
,另存为neo4j中的节点)和更新的引用(类型为:Person
的学生)之间的多个关系,保存为neo4j中的不同节点),同时删除与旧参考相关的旧关系(在这种情况下为学生)。这是更新neo4j中的一系列子文档引用的结果。
除了在查询中创建的叉(笛卡尔)乘积外,主要问题是以下查询创建的关系是删除的关系的两倍:
MATCH (doc:Class {m_id: '5bf5b9df11c344021de89395'}),
(I:Person {m_id: '5bf5b9df11c344021de89393'}),
(II:Person {m_id: '5bf5b9df11c344021de89394'}),
(:Class {m_id: '5bf5b9df11c344021de89395'})-[r]->()
WHERE type(r) IN ["HAS_STUDENT"]
CREATE (doc)-[:HAS_STUDENT]->(I), (doc)-[:HAS_STUDENT]->(II)
DELETE r;
这将删除2个关系(这是正确的),但会创建4个新关系(应为2个)。
使用CREATE
形式的单个CREATE (I)<-[:HAS_STUDENT]-(doc)-[:HAS_STUDENT]->(II)
也不是有效的选择,因为此查询是在for循环中创建的,并且可能会创建越来越多的新关系。 (也是我要优化查询的主要原因。)
我有该查询的多个版本,所有版本均产生相同的输出。问题可能出在WHERE
部分,因为当我使用下面的查询时,它会创建正确数量的关系。 唯一缺少的是它应该只删除旧的关系:
MATCH (doc:Class {m_id: '5bf5b9df11c344021de89395'}),
(I:Person {m_id: '5bf5b9df11c344021de89393'}),
(II:Person {m_id: '5bf5b9df11c344021de89394'})
CREATE (doc)-[:HAS_STUDENT]->(I), (doc)-[:HAS_STUDENT]->(II)
WITH doc
MATCH (doc)-[r]->(n)
WHERE type(r) IN ["HAS_STUDENT"]
DELETE r;
因此,除了解决问题外,我的主要问题是如何针对所描述的行为有效地编写此查询。我使用neo4j驱动程序,因此可以使用参数。
注意::I和II稍后将用作变量来分配唯一的关系值,这就是为什么我没有为MATCH
节点使用单个:Person
的原因。
还使用IN
子句中的关系类型的WHERE
,因为可能会创建不同类型的关系(并因此删除了该类型的旧关系)。
最后,我已经研究过UNWIND
和FOREACH
,但似乎无法将它们放入所描述的用例中。
答案 0 :(得分:2)
密码的问题是,每行
所以在这里
MATCH (doc:Class {m_id: '5bf5b9df11c344021de89395'}), // 1
(I:Person {m_id: '5bf5b9df11c344021de89393'}), // 1
(II:Person {m_id: '5bf5b9df11c344021de89394'}), // 1
(:Class {m_id: '5bf5b9df11c344021de89395'})-[r]->() // 2
// 1 match * 1 match * 1 match * 2 match = 2 rows
WHERE type(r) IN ["HAS_STUDENT"]
CREATE (doc)-[:HAS_STUDENT]->(I), (doc)-[:HAS_STUDENT]->(II)
// 2 create * 2 rows = 4 new relations
DELETE r;
因此,您需要先使用DISTINCT剪掉“重复的”行
MATCH (doc:Class {m_id: '5bf5b9df11c344021de89395'}),
(:Class {m_id: '5bf5b9df11c344021de89395'})-[r]->()
WHERE type(r) IN ["HAS_STUDENT"]
DELETE r;
WITH DISTINCT doc
MATCH (I:Person {m_id: '5bf5b9df11c344021de89393'}),
(II:Person {m_id: '5bf5b9df11c344021de89394'})
CREATE (doc)-[:HAS_STUDENT]->(I), (doc)-[:HAS_STUDENT]->(II)