我正在使用 Neo4j ,我对如何在 Cypher 中执行某些查询以及保持高性能表示担忧。
我的图表中包含标签为“Thing”的节点。并且每个节点都具有属性“ pk ”(整数)
所以,给出像 [123,34,125] 这样的pks列表,我想创建/更新(如果存在)所有对的节点之间的关系我们可以得到他们的组合。
(123,34),(123,125),(32,125)并且对于每个节点之间的r设置 r.weight = 0 (如果已创建关系)或 r.weight + = 1 (如果已存在)
目前我使用itertools.combination(pks,2)在Python中进行组合,然后我为每对c1,c2执行组合:
'MATCH (c1:Thing {pk: %(c1_pk)s}), (c2:Thing {pk: %(c2_pk)s}) ' \
'CREATE UNIQUE c1-[r:KNOWS]-c2 ' \
'SET r.weight=coalesce(r.weight, 0)+1 RETURN c1, r.weight, c2' % {'c1_pk': c1_pk,
'c2_pk': c2_pk}
但是我不喜欢为每一对调用该查询,因为当pks列表很长时性能很差,因为组合和查询将是长度(pks)*(长度(pks)-1)
我怎么能这样做?
修改 大约有15000个“Thing”节点,并且总是具有相同的数量。 并且有一个约束是pk属性唯一(t:Thing t.pk是唯一的)
答案 0 :(得分:0)
您对创建这些成对关系的位置没有任何限制,因此您尝试将此作为笛卡尔产品。如果你有很多节点,它会变慢。
但是我在查询中看到的一个错误是你试图创建两次关系;让我们说你想从X创建一个关系 - >你曾经为X做过一次 - > Y,然后再次为Y - > X
你可以通过只做一次一次来减少一半,如下所示:
MATCH (c1:Thing {pk: %(c1_pk)s}), (c2:Thing {pk: %(c2_pk)s})
CREATE UNIQUE c1-[r:KNOWS]-c2
SET r.weight=coalesce(r.weight, 0)+1 RETURN c1, r.weight, c2' % {'c1_pk': c1_pk,
'c2_pk': c2_pk}
WHERE c1.id < c2.id
请注意,我们按ID排序节点。由于它们都有不同的ID,因此您可以执行X - &gt; Y,但不是Y - &gt; X
这使得整个过程从长度(pks)*长度(pks)-1变为:(长度(pks)*长度(pks)-1)/ 2。
但是,没有办法解决你想要做的事情是O(n ^ 2)