【发布时间】:2018-11-21 21:00:22
【问题描述】:
我目前正在编写一个 mongoose 插件来使用 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 (I)<-[:HAS_STUDENT]-(doc)-[:HAS_STUDENT]->(II) 形式的单个CREATE 不是有效选项,因为此查询是在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 稍后将用作分配唯一关系值的变量,这就是为什么我没有为 :Person 节点使用单个 MATCH。
此外,使用 WHERE 子句中的关系类型的 IN 是因为可能会创建不同类型的关系(因此删除了该类型的旧关系)。
最后,我已经研究了UNWIND 和FOREACH,但似乎无法将它们放入所描述的用例中。
【问题讨论】:
-
对于这个用例,看起来您应该使用 Neo4j javascript Object Graph Mapper (OGM)。另外,你有APOC插件吗?澄清一下,您是否只是试图重新映射关系以在不同的节点处结束?
-
嗯(OGM)实际上是我想要创建的。对于 APOC,我真的不希望使用该库的人像外部 OGM 那样依赖 APOC。最后一部分,是的,但我想将 create 子句与那些将创建与属性的关系的子句结合起来。这就是为什么我认为最好的选择是删除所有旧关系并创建新关系。