我有一组节点,都标记为Word。我想用一个名为Distance的关系将每个单词连接到所有其他单词。我做了以下查询:
match (word1:Word) with word1 match (word2:Word) where word1 <> word2 merge (word1)-[distance:DISTANCE ]->(word2) return word1, distance, word2
它永远运行。只有约600个节点,虽然我期望600 * 600的关系,但查询不应该运行两个小时!它在Java中比在Neo4j中更快。你有什么建议让它更快?我已经在其中一个属性上添加了一个索引,但它没有改进。
答案 0 :(得分:3)
一些观察结果:
MERGE
次操作。因子2
的原因是因为每对单词(例如,x和y)将被看到两次(如x / y和y / x)。你(大概)只想执行一半的操作。DISTANCE
关系 - 一个方向都是一个。这(大概)是你想要(或需要)的关系数量的两倍。这是一个修改过的查询,可能会解决上述问题。 ID(w1) < ID(w2)
测试确保一对中的2个单词不相同并且同一对只处理一次。它还使用APOC过程apoc.periodic.iterate在单独的事务中一次创建10K关系。
CALL apoc.periodic.iterate(
'MATCH (w1:Word), (w2:Word) WHERE ID(w1) < ID(w2) RETURN w1, w2',
'CREATE (w1)-[:DISTANCE]->(w2)',
{batchSize:10000, parallel:true}) YIELD batches, total
RETURN *
注意1:此查询假定您在数据库中没有任何DISTANCE
关系的情况下开始,因此它使用更便宜的CREATE
子句而不是MERGE
。如果已存在DISTANCE
关系,则使用MERGE
代替(但如果第一个关系方向相反,这可能会在同一对之间创建第二个关系)。
注意2:并行执行批处理应该是安全的,因为新的Cypher代码无法解决问题#2。如果2个事务试图同时在相同的2个节点之间以相反的方向创建关系,则可能导致deadlock,这将导致至少一个事务失败。 < / p>
注3:此查询假定第一个语句(带有MATCH
子句)本身不会耗尽内存或处理时间过长。如果该假设是错误的,那么使用apoc.periodic.commit的适当修改的查询应该有效。