Neo4j使用py2neo从pandas dataframe创建节点和关系

Fab*_*nna 6 python neo4j cypher pandas py2neo

使用py2neo从Neo4j数据库上的密码查询获取pandas数据帧的结果非常简单,如下所示:

>>> from pandas import DataFrame
>>> DataFrame(graph.data("MATCH (a:Person) RETURN a.name, a.born LIMIT 4"))
   a.born              a.name
0    1964        Keanu Reeves
1    1967    Carrie-Anne Moss
2    1961  Laurence Fishburne
3    1960        Hugo Weaving
Run Code Online (Sandbox Code Playgroud)

现在我正在尝试使用py2neo创建(或更好的MERGE)从pandas数据帧到Neo4j数据库的一组节点和关系.想象一下,我有一个像以下数据帧:

LABEL1 LABEL2
p1 n1
p2 n1
p3 n2
p4 n2
Run Code Online (Sandbox Code Playgroud)

其中标签是列标题,属性是值.我想为我的数据帧的每一行重现以下cypher查询(对于第一行作为示例):

query="""
    MATCH (a:Label1 {property:p1))
    MERGE (a)-[r:R_TYPE]->(b:Label2 {property:n1))
"""
Run Code Online (Sandbox Code Playgroud)

我知道我可以告诉py2neo graph.run(query),或者甚至LOAD CSV以相同的方式运行cypher 脚本,但我想知道我是否可以遍历数据帧并逐行应用上面的查询WITHIN py2neo.

Wil*_*yon 10

您可以使用DataFrame.iterrows()迭代DataFrame并对每一行执行查询,并将行中的值作为参数传入.

for index, row in df.iterrows():
    graph.run('''
      MATCH (a:Label1 {property:$label1})
      MERGE (a)-[r:R_TYPE]->(b:Label2 {property:$label2})
    ''', parameters = {'label1': row['label1'], 'label2': row['label2']})
Run Code Online (Sandbox Code Playgroud)

这将每行执行一个事务.我们可以将多个查询批处理到一个事务中以获得更好

tx = graph.begin()
for index, row in df.iterrows():
    tx.evaluate('''
      MATCH (a:Label1 {property:$label1})
      MERGE (a)-[r:R_TYPE]->(b:Label2 {property:$label2})
    ''', parameters = {'label1': row['label1'], 'label2': row['label2']})
tx.commit()
Run Code Online (Sandbox Code Playgroud)

通常,我们可以在单个事务中批量处理~20k数据库操作.


Ann*_*ina 5

我发现建议的解决方案对我不起作用。即使节点已经存在,上面的代码也会创建新节点。为确保您不会创建任何重复项,我建议在之前匹配ab节点merge

tx = graph.begin()
for index, row in df.iterrows():
    tx.evaluate('''
       MATCH (a:Label1 {property:$label1}), (b:Label2 {property:$label2})
       MERGE (a)-[r:R_TYPE]->(b)
       ''', parameters = {'label1': row['label1'], 'label2': row['label2']})
tx.commit()
Run Code Online (Sandbox Code Playgroud)

同样在我的情况下,我必须同时添加关系属性(请参阅下面的代码)。此外,我有 500k+ 关系要添加,所以我预计会遇到 java 堆内存错误。我通过放置begin()commit()在循环内解决了这个问题,因此对于每个新关系都会创建一个新事务:

for index, row in df.iterrows():
    tx = graph.begin()
    tx.evaluate('''
       MATCH (a:Label1 {property:$label1}), (b:Label2 {property:$label2})
       MERGE (a)-[r:R_TYPE{property_name:$p}]->(b)
       ''', parameters = {'label1': row['label1'], 'label2': row['label2'], 'p': row['property']})
    tx.commit()
Run Code Online (Sandbox Code Playgroud)