在Neo4j 1.8中查找重复节点的有效方法?

时间:2015-02-03 15:24:01

标签: performance neo4j cypher

我试图以编程方式找到Neo4j 1.8数据库中的所有重复节点(使用Neo4j 1.8)。 需要检查的节点都有一个(非索引)属性externalId,我想找到它的副本。这是我所获得的Cypher查询:

            START n=node(*), dup=node(*) WHERE 
                HAS(n.externalId) AND HAS(dup.externalId) AND 
                n.externalId=dup.externalId AND 
                ID(n) < ID(dup) 
                RETURN dup

数据中的节点少于10K,而externalId的节点少于1K。 上面的查询正在运行,但似乎表现不佳。是否有更少的内存消耗方式来做到这一点?

2 个答案:

答案 0 :(得分:2)

尝试此查询:

START n=node(*)
WHERE HAS(n.externalId)
WITH n.externalId AS extId, COLLECT(n) AS cn
WHERE LENGTH(cn) > 1
RETURN extId, cn;

它避免使用节点的笛卡尔积。它找到不同的externalId值,收集具有相同ID的所有节点,然后过滤掉非重复的ID。结果中的每一行都包含一个externalId和一个具有该id的重复节点的集合。

答案 1 :(得分:2)

start子句包含完整的图形扫描,然后组装整个节点集的笛卡尔积(10k * 10k = 100m对开始),然后根据其中的条件缩小非常大的列表条款。 (也许这里有密码优化?我不确定)

我认为在externalId上添加一个索引将是一个明显的胜利,并且现在可能提供足够的性能提升,但你也可以用不同的方式查找重复项,可能是这样的:

START n=node(*)
WHERE HAS(n.externalId)
WITH n
ORDER BY ID(n) ASC 
WITH count(*) AS occurrences, n.externalId AS externalId, collect(ID(n)) AS ids
WHERE occurrences > 1
RETURN externalId, TAIL(ids)