Neo4j:如何通过Cypher删除数据库中所有重复的关系?

6
我有一个庞大的数据库,有很多节点(10mil+)。整个数据库中只有一种类型的关系。然而,有许多节点之间存在重复的关系。我目前拥有的是这个Cypher脚本,可以找到所有具有重复项的节点对,然后运行一个Python脚本来清理每个节点对中的重复关系(只保留一个唯一的关系)。
match (a)-[r]->(b) with a,b, count(*) as c where c>1 return a.pageid, b.pageid, c LIMIT 100000;
这对于小型数据库效果还不错,但当我在大型数据库上运行它时,最终会出现有关堆内存耗尽的异常(将盒子增加更多并不能解决问题)。
因此,问题有两个方面: 1)是否有任何可以放在关系上的索引(现在没有)可以帮助加快速度? 2)是否有一个Cypher查询可以(以快速或至少可靠的方式)删除数据库中的所有重复关系,仅保留每个节点对中已经存在的一个唯一关系?
附言:我正在运行neo4j 2.0.1在Ubuntu(12something)AWS盒子上。
我知道有这样一个答案:stackoverflow,但他所问的更具体(反对已知的两个节点),而且全数据库覆盖的答案已经无法运行了(语法改变?)。
提前感谢!

1
只是一些想法:你是否尝试过更小的批次,比如每次100个,将它们传递给你的Python脚本?(不确定你是否需要一次获取10万个)你的节点上是否有索引,可以针对特定节点类型运行此操作,从而减少总节点空间? - David Makogon
2个回答

8
在链接的SO问题中,使用db全局查询时出现了什么错误?尝试在FOREACH中用|替换:,这是我能看到的唯一破坏语法差异。与2.x的方式说相同的事情,除了适应于您在数据库中只有一种关系类型外,可能是:
MATCH (a)-[r]->(b)
WITH a, b, TAIL (COLLECT (r)) as rr
FOREACH (r IN rr | DELETE r)

我认为WITH管道会在没有重复项时保留空尾部,而且我不知道循环遍历空集合的代价有多高——我的感觉是在WITH之后引入限制的地方应该是使用过滤器, 如下所示:

MATCH (a)-[r]->(b)
WITH a, b, TAIL (COLLECT (r)) as rr
WHERE length(rr) > 0 LIMIT 100000
FOREACH (r IN rr | DELETE r)

由于这个查询根本不涉及属性(与你的查询相反,它返回(a)和(b)的属性),所以我认为对于像你这样的中等规模图形来说,它不应该非常占用内存,但是你需要尝试限制一下。

如果内存仍然是一个问题,那么如果有任何方法可以限制要处理的节点(而不涉及属性),那也是一个好主意。如果你的节点可以通过标签区分,请尝试逐个标签运行查询。

MATCH (a:A)-[r]->(b) //etc..
MATCH (a:B)-[r]->(b) //etc..

1
这个FOREACH是如何知道只删除多余的关系,保留一个(例如,如果有3个相同的关系,则保留1个并删除2个)。在运行此操作之前,我只是想了解一下。导入这些数据花费了2周时间 :-/ - Diaspar
1
先进行测试,只需在http://console.neo4j.org或类似网站上设置一个模拟数据库即可。原因是您只持有集合的尾部,也就是除了第一个元素以外的所有元素,因此第一个元素将不受foreach的影响。 - jjaderberg
2
它成功了!!之前的尝试会持续数小时,最终因为堆“内存不足”异常而失败。这个东西只用了2.5分钟就完成了!! - Diaspar
1
一年后使用此代码出现语法错误。Neo4j 不知何故不喜欢 LIMIT 100000 - Monica Heddneck

2

这是原始回答(Original Answer)的一个版本,已经被修复(通过插入WITH rr 子句)以适应更近期的 neo4j 版本,并且速度应该更快(因为它只在需要时创建新的TAIL列表):

MATCH (a)-[r]->(b)
WITH a, b, COLLECT(r) AS rr
WHERE SIZE(rr) > 1
WITH rr
LIMIT 100000
FOREACH (r IN TAIL(rr) | DELETE r);

[更新]

如果你只想删除相同类型的重复关系,则可以按照以下步骤操作:

MATCH (a)-[r]->(b)
WITH a, b, TYPE(r) AS t, COLLECT(r) AS rr
WHERE SIZE(rr) > 1
WITH rr
LIMIT 100000
FOREACH (r IN TAIL(rr) | DELETE r);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接