我的上一个问题因重复Confused about MERGE sometimes creating duplicate relationship而被关闭,但是我无法找到解决方案,这会处理重复的关系,而不是重复的节点。
当用户VISITED
其他用户的个人资料
MATCH (you:User {user_id: { myId }}), (youVisited:User {user_id: { id }})
MERGE (you)-[yvr:VISITED]->(youVisited)
SET yvr.seen = false, yvr.created_at = timestamp()
RETURN yvr.created_at as visited_at
我注意到在极少数情况下会发生重复的[:VISITED]
关系。对于(1057)-[:VISITED]->(630)
,两者都具有相同的属性,并且实际上只应该是一个[:VISITED]
无论什么(下次用户访问时,它应该只是MERGE
{{1}并更新相同用户节点之间的[:VISITED]
:
[:VISITED {created_at: ..., seen: false}]
我认为{
created_at: 1485800172734,
seen: false
}
要防止这种情况发生?显然不是,为什么会发生这种情况,我怎样才能确保不会发生这种情况呢?
我查了一些其他的东西,但我不确定这些信息是否可靠或是最新的。例如:http://neo4j.com/docs/developer-manual/current/cypher/clauses/create-unique/,我应该使用MERGE
吗?我认为CREATE UNIQUE
几乎是一个更好的替代品。
答案 0 :(得分:2)
我同意在某些情况下,MERGE
和CREATE UNIQUE
可用于同一目的。但是,MERGE
不会取代CREATE UNIQUE
。
例如,MERGE
允许多个匹配,并且其模式必须完全匹配图形才被视为匹配 - 它将简单地复制部分匹配;另一方面,CREATE UNIQUE
会在多个匹配项上出错,并允许部分匹配 - 它会尝试重新使用图表的现有部分并添加缺少的部分。
正如docs中所提到的,关系的唯一性似乎也存在差异,即您所遇到的问题:
MERGE可能是您想要使用的而不是CREATE UNIQUE。但请注意,MERGE并不能保证关系的独特性。
我会让Neo4j的开发人员准确解释这些保证是什么。我只能说,在你的特定情况下,CREATE UNIQUE
似乎比MERGE
更合适:如果你的意图是只允许一个用户与另一个用户之间的单一VISITED
关系 - 他的上次访问 - 多个VISITED
关系违反了您的数据模型,然后一定要使用CREATE UNIQUE
来记录此意图,并在数据库级别强制执行同一时间。
在这种情况下,可以说VISITED
关系也没有特别好的命名,因为它意味着可能有更多:每次用户访问另一个用户的个人资料时都有一个。
答案 1 :(得分:1)
正如我的评论中所提到的,在Neo4j切换到COST规划师时,有一个locking bug MERGE。
据我所知,它的工作原理如下:
由于该错误,双重检查锁定没有发生,因此在MERGE确定关系不存在之后,它会锁定节点以准备创建关系,但是那里有“sa”。在存在检查关系和锁定之间的竞争条件,因此并发MERGE或CREATE可能在获取锁之前创建了关系,从而导致创建重复关系。
修复将确保MERGE在获取锁之后再次检查是否存在关系。这应该恢复MERGE的并发保证。
截至2017年2月2日,此修复程序尚未发布到当前的Neo4j版本中。
与此同时,您可以在MERGE之前显式锁定相关节点,以防止竞争条件。
您可以通过在相关节点上设置/删除不存在的值来执行此操作,或使用APOC locking procedures。