高效添加关系。Neo4j

0 投票
1 回答
39 浏览
提问于 2025-04-14 17:38

我有一个大约有500万行和两列的CSV文件,列名分别是“client”(客户)和“product”(产品)。每个客户和产品在我的neo4j图数据库中都有一个对应的ID。这里面可能会有各种重复的情况,这没问题。

我在Python中写了以下代码:

j=1
batch_size=500
nbatch=len(client_product)//batch_size+1
for i in range(0,len(client_product),batch_size):
    j+=1
    print(f"{j}/{nbatch}")
    batch = client_product.iloc[i:i + batch_size]
    my_dict = batch.to_dict('records')
    my_dict_str = str(my_dict)
    my_dict_str=dictToPropertiesSingleValue(str(my_dict))
    tq=f"""UNWIND {my_dict_str} AS row
    MATCH (n:client), (k:product)
    WHERE ID(n) = row.client_ID AND ID(k) = row.product_ID
    CREATE (n)-[r:client_product]->(k)
    return count(r)"""
    runq(tq)

中间的部分

my_dict = batch.to_dict('records')
my_dict_str = str(my_dict)
my_dict_str=dictToPropertiesSingleValue(str(my_dict))

是把一个字典格式化成neo4j可以读懂的列表。就像这样:

[ {client_ID: 918906,product_ID: 40320},
 {client_ID: 918920,product_ID: 40320},
 {client_ID: 918921,product_ID: 40320},
 {client_ID: 918953,product_ID: 40321},
 {client_ID: 918955,product_ID: 40322},
 {client_ID: 918960,product_ID: 40323},
 {client_ID: 919018,product_ID: 40323},
 {client_ID: 919517,product_ID: 40323},
 {client_ID: 919702,product_ID: 40323},
 {client_ID: 919703,product_ID: 40324},
 {client_ID: 919743,product_ID: 40324},
 {client_ID: 919744,product_ID: 40324},
 {client_ID: 919745,product_ID: 40324},
 {client_ID: 919764,product_ID: 40325}]

我真的很难找到一个更快的方法来上传这些数据。上传几百万条关系应该只需要几分钟,但我现在却要花4个小时。有没有什么建议?

1 个回答

1

其实你不需要写特别复杂的代码来执行10,000个单独的Cypher查询,这就是为什么会花那么长时间。你可以只用一个查询,利用LOAD CSV这个功能,它专门用来直接从CSV数据导入。你还可以使用在事务中调用子查询,这样可以支持批量导入大量数据

举个例子(我使用的批量大小是5000,但你可以尝试不同的数值,看看哪个速度更快):

LOAD CSV WITH HEADERS FROM 'file:///client_product.csv' AS r
CALL {
  WITH r
  MATCH (n), (k)
  WHERE ID(n) = r.client_ID AND ID(k) = r.product_ID
  CREATE (n)-[:client_product]->(k)
} IN TRANSACTIONS OF 5000 rows

注意事项:

  1. 上面的查询假设CSV文件的开头有一行标题(比如“client_ID,product_ID”)。
  2. 如果是从本地文件加载,查看文档中的“文件URL的配置设置”部分。
  3. LOAD CSV也可以从http网址加载,如果CSV文件在网上可以访问的话。
  4. 如果你需要避免创建重复的关系,使用MERGE而不是CREATE(不过这样会稍微慢一点)。

撰写回答