我试图以编程方式找到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。
上面的查询正在运行,但似乎表现不佳。是否有更少的内存消耗方式来做到这一点?
答案 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)