【问题标题】:Efficient duplicate node finding in neo4jNeo4j 中高效的重复节点查找
【发布时间】:2015-12-29 04:17:12
【问题描述】:

下一个 Neo4j 版本的功能请求:Neo4j 已经支持以排序顺序保持属性的索引,从而允许快速查找。例如。对于一个人的名字,一个人的索引可能如下所示:

爱丽丝 鲍勃 颂歌 戴夫 艾米丽 (....)

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

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

用 MATCH (b:person) 解释 MATCH (a:person) WHERE a.name = b.name RETURN a, b LIMIT 5

显示了一个 CartesianProduct 步骤,然后是一个 Filter 步骤。但是有了名字的索引,人们可以对一个列表进行线性扫描,例如:

爱丽丝 爱丽丝 爱丽丝 鲍勃 颂歌 颂歌 戴夫 艾米丽 坦率 坦率 坦率 (....)

比较项目#1 到#2、#2 到#3 等等,以在每次扫描的 O(n) 时间内构建所有重复项的有序列表。 Neo4j 似乎不支持这一点,但它对我的应用程序非常有用,所以我想提出一个请求。

【问题讨论】:

    标签: neo4j


    【解决方案1】:

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

    所以我想知道 Neo4j 是否认为属性是特殊的。如果您在标签/属性上有索引(可以使用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 它时,这似乎减少了我的 DB 命中率。

    由于您谈论的是同一组对象,因此另一种方法是按名称对节点进行分组,然后为每个组提取对。像这样:

    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
    

    在这里,我们为每个唯一名称收集一个数组(如果我们想不区分大小写,我们也可以使用小写/大写)然后 UNWIND 两次以获取该数组的笛卡尔积。由于我们是按组进行工作,因此这应该比将每个节点与其他每个节点进行比较要快得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多