我的数据库模型有用户和 MAC 地址。一个用户可以有多个MAC地址,但一个MAC只能属于一个用户。如果某个用户设置了他的 MAC,并且该 MAC 已经链接到另一个用户,则现有关系将被删除,并在新所有者和该 MAC 之间创建新关系。换句话说,MAC 在用户之间移动。
这是我用来分配 MAC 地址的 Cypher 查询的一个特定实例:
MATCH (new:User { Id: 2 })
MERGE (mac:MacAddress { Value: "D857EFEF1CF6" })
WITH new, mac
OPTIONAL MATCH ()-[oldr:MAC_ADDRESS]->(mac)
DELETE oldr
MERGE (new)-[:MAC_ADDRESS]->(mac)
该查询在我的测试中运行良好,但在生产中,由于某种奇怪的原因它有时创建重复项MacAddress
节点(以及用户和每个节点之间的新关系)。也就是说,一个特定的用户可以有多个MacAddress
具有相同的节点Value
.
我可以看出它们是不同的节点,因为它们具有不同的节点 ID。我也确信Value
s 完全相同,因为我可以做collect(distinct mac.Value)
对它们进行处理,结果是一个包含一个元素的集合。上面的查询是代码中唯一创建的查询MacAddress
nodes.
我正在使用 Neo4j 2.1.2。这里发生了什么?
谢谢,
扬
您确定这是您正在运行的全部查询吗?MERGE
有一个非常常见的陷阱,它合并了您提供的所有内容。所以这就是人们的期望:
neo4j-sh (?)$ MERGE (mac:MacAddress { Value: "D857EFEF1CF6" });
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 1
Properties set: 1
Labels added: 1
1650 ms
neo4j-sh (?)$ MERGE (mac:MacAddress { Value: "D857EFEF1CF6" });
+--------------------------------------------+
| No data returned, and nothing was changed. |
+--------------------------------------------+
17 ms
neo4j-sh (?)$ match (mac:MacAddress { Value: "D857EFEF1CF6" }) return count(mac);
+------------+
| count(mac) |
+------------+
| 1 |
+------------+
1 row
200 ms
到目前为止,一切都很好。这就是我们所期望的。现在看这个:
neo4j-sh (?)$ MERGE (mac:MacAddress { Value: "D857EFEF1CF6" })-[r:foo]->(b:SomeNode {label: "Foo!"});
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 2
Relationships created: 1
Properties set: 2
Labels added: 2
178 ms
neo4j-sh (?)$ match (mac:MacAddress { Value: "D857EFEF1CF6" }) return count(mac);
+------------+
| count(mac) |
+------------+
| 2 |
+------------+
1 row
2 ms
等等,这里发生了什么?我们再次指定了相同的 MAC 地址,为什么会创建重复的?
The 关于 MERGE 的文档指定“MERGE 不会部分使用现有模式 — 要么全有要么全无。如果需要部分匹配,可以通过将模式拆分为多个 MERGE 子句来完成”。因为当我们运行这条路径时MERGE
整个路径并不存在,它会创建其中的所有内容,包括重复的 mac 地址节点。
经常出现关于创建重复节点的问题MERGE
,100 次中有 99 次,这就是正在发生的事情。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)