使用cypher语句根据结点属性删除相同结点及其关系
原文链接: https://gist.github.com/jruts/fe782ff2531d509784a24b655ad8ae76
这个问题很好理解,在数据库中有id相同的结点存在。
这事看上去挺简单,但当真真做时才知道,并没有想的那么容易。
第一步
我首先尝试着找出重复的结点,这个看上去很简单。
MATCH (g:geo) WITH g.id as id, collect(g) AS nodes WHERE size(nodes) > 1RETURN nodes
这个查询得到所有geo标签的结点,然后创建id属性个数大于1的结点列表。这个查询结果就是得到重复的带有geo标签的结点列表。示例结果如下:
第二步
接下来我要尝试着删除重复的,当然要留一个。
MATCH (g:geo) WITH g.id as id, collect(g) AS nodes WHERE size(nodes) > 1FOREACH (g in tail(nodes) | DELETE g)
这个语句会出错:
org.neo4j.kernel.api.exceptions.ConstraintViolationTransactionFailureException: Cannot delete node<866>, because it still has relationships. To delete this node, you must first delete its relationships.
看上去我们好像快要搞定了,但是我先解释一下这个查询。我们使用之前相应的查询,但是我们没有返回结点,而是遍历 tail(nodes) 的结点,依次删除这些结点。
tail 函数能够返回一个列表中除了首结点之外的所有结点,所以,我们能确保有一个结点不被删除。
第三步
上面的错误显示,我们在删除结点之前需要先删除他们关系。
MATCH (g:geo) WITH g.id as id, collect(g) AS nodes WHERE size(nodes) > 1UNWIND tail(nodes) as tailsMATCH (tails)-[r]-()DELETE r
重复的结点的关系被成功删除了,当我们再次运行第二步的语句时,重复的结点也被删除了。
解决方案
先删除重复结点的重复关系MATCH (g:geo) WITH g.id as id, collect(g) AS nodes WHERE size(nodes) > 1 UNWIND tail(nodes) as tails MATCH (tails)-[r]-() DELETE r
再删除重复的结点MATCH (g:geo) WITH g.id as id, collect(g) AS nodes WHERE size(nodes) > 1 FOREACH (g in tail(nodes) | DELETE g)
希望这些能帮助到大家。
译者言:事实上有更简单的方法,一步完成这种删除。MATCH (g:geo)WITH g.id as id, collect(g) AS nodes WHERE size(nodes) > 1FOREACH (g in tail(nodes) | DETACH DELETE g)
百度一定要配张图,用什么呢?