Jan*_*sch 7 merge neo4j cypher
我的数据库模型有用户和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)
Run Code Online (Sandbox Code Playgroud)
查询在我的测试中运行正常,但在生产中,由于某些奇怪的原因,它有时会创建重复的MacAddress节点(以及用户和每个节点之间的新关系).也就是说,特定用户可以具有多个MacAddress具有相同节点的节点Value.
我可以说它们是不同的节点,因为它们具有不同的节点ID.我也确定Values完全相同,因为我可以collect(distinct mac.Value)对它们进行操作,结果是一个带有一个元素的集合.上面的查询是代码中唯一创建MacAddress节点的查询.
我正在使用Neo4j 2.1.2.这里发生了什么?
谢谢,Jan
您确定这是您正在运行的所有查询吗? 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
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.这就是我们的期望.现在看这个:
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
Run Code Online (Sandbox Code Playgroud)
等等,WTF发生在这里?我们再次只指定了相同的MAC地址,为什么要创建重复?
关于MERGE的文档规定"MERGE不会部分使用现有模式 - 它是全部或全部.如果需要部分匹配,可以通过将模式拆分为多个MERGE子句来实现".因此,当我们运行此路径时MERGE,整个路径尚不存在,它会在其中创建所有内容,包括重复的mac地址节点.
经常有关于创建重复节点的问题MERGE,以及100次中的99次,这就是正在发生的事情.
这是我从Neo4j的支持中得到的回应(强调我的):
我已经得到了我们团队的一些反馈,目前已经知道这可以在没有约束的情况下发生.MERGE实际上是MATCH或CREATE - 这两个步骤在事务中独立运行.鉴于并发执行和"读取已提交"隔离级别,两者之间存在竞争条件.
团队已经就如何在并发性方面提供更高的保证做了一些讨论,并确实将其作为要考虑的功能请求.
同时,他们向我保证使用约束将提供您正在寻找的独特性.