在neo4j中有效的重复节点查找

时间:2015-12-29 04:17:12

标签: neo4j

下一个Neo4j版本的功能请求:Neo4j已经支持以排序顺序保存属性的索引,允许快速查找。例如。对于一个人的名字,可能有一个看起来像这样的索引:

翘 短发 颂歌 戴夫 艾米莉 (....)

所以可以用二分搜索(O(log n))而不是线性扫描(O(n))来查找“Dave”。

但是,也可以使用索引来有效地查找重复项(某些属性具有相同值的节点)。例如,如果想要一个共享相同名字的每一组“人”节点的列表,那么Neo4j 2.3似乎要做什么(通过Cypher中的EXPLAIN)运行每个节点的名字与其他所有名字的比较,是O(N ^ 2)。例如。这个查询:

使用MATCH(b:person)的EXPLAIN MATCH(a:person)WHERE a.name = b.name返回a,b LIMIT 5

显示CartesianProduct步骤,后跟Filter步骤。但是使用名字索引,可以对列表进行线性扫描,例如:

翘 爱丽丝 爱丽丝 短发 颂歌 颂歌 戴夫 艾米莉 坦率 坦率 坦率 (....)

将项目#1与#2,#2和#3进行比较,依此类推,以每次扫描的O(n)时间构建所有重复项的有序列表。 Neo4j似乎不支持这一点,但它对我的应用程序非常有用,所以我想提出请求。

1 个答案:

答案 0 :(得分:0)

我对您可能会尝试的内容提出了一些建议,但如果您发现它们不足(并且没有其他人有更好的想法),我建议您向Neo4j GitHub issues list提交新的功能提示。

所以我想知道Neo4j是否认为属性特别。如果您在标签/属性上有一个索引(可以使用select dev_cost / sell_cost from software ; 创建),那么将属性与字符串进行比较应该非常有效。我尝试将名称作为变量传递,并且在我的小测试数据库中似乎有更少的数据库命中:

CREATE INDEX ON :person(name)

当我MATCH (a:person) WITH a, a.name AS name MATCH (b:person) WHERE name = b.name RETURN a, b LIMIT 5 时,这似乎会减少数据库命中率。

另一种方法是,因为你在谈论同一组对象,就是按名称对节点进行分组,然后为每个组拉出对。像这样:

PROFILE

这里我们为每个唯一名称收集一个数组(如果我们想要不区分大小写,我们也可以降低/上限),然后两次MATCH (a:person) WITH a.name AS name, collect(a) AS people UNWIND people AS a UNWIND people AS b WITH name, a, b WHERE a <> b RETURN a, b LIMIT 50 来获得数组的笛卡尔积。由于我们正在逐个组地工作,这比将每个节点与每个其他节点进行比较要快得多。