首页 > 解决方案 > 为一组节点创建每两个节点之间的关系

问题描述

我在neo4j中创建了很多节点,这些节点的属性都是一样的,都有user_id和item_id,使用的代码如下:

LOAD CSV WITH HEADERS FROM 'file://data.csv' AS row
CREATE (main:Main_table {USER_ID: row.user_id,
                         ITEM_ID: row.item_id}
       )
CREATE INDEX ON :Main_table(USER_ID);
CREATE INDEX ON :Main_table(ITEM_ID);

现在我想在具有相同 user_id 或 item_id 的节点之间创建关系。例如,如果节点 A、B 和 C 的 USER_ID 相同,我想创建(A)-[:EDGE]->(B),(A)-[:EDGE]->(C)(B)-[:EDGE]->(C). 为了实现这个目标,我尝试了以下代码:

MATCH (a:Main_table),(b:Main_table)
WHERE a.USER_ID = b.USER_ID
CREATE (a)-[:USER_EDGE]->(b);
MATCH (a:Main_table),(b:Main_table)
WHERE a.ITEM_ID = b.ITEM_ID
CREATE (a)-[:ITEM_EDGE]->(b);

但是由于数据量很大(3000000个节点,100000个用户),这个过程很慢,怎么才能快速完成这个过程呢?任何帮助将不胜感激!

标签: neo4jcypher

解决方案


您的查询导致笛卡尔积,并且 Cypher 规划器不使用索引来优化涉及节点属性比较的节点查找。

像这样的查询(而不是您的USER_EDGE查询)可能会更快,因为它不会导致笛卡尔积:

MATCH (a:Main_table)
WITH a.USER_ID AS id, COLLECT(a) AS mains
UNWIND mains AS a
UNWIND mains AS b
WITH a, b
WHERE ID(a) < ID(b)
MERGE (a)-[:USER_EDGE]->(b)

该查询使用聚合函数 COLLECT来收集具有相同USER_ID值的节点,并使用ID(a) < ID(b)测试来确保ab不是相同的节点,并防止重复关系(在相反的方向上)。


推荐阅读