【问题标题】:Neo4j create nodes and relationships from pandas dataframe with py2neoNeo4j 使用 py2neo 从 pandas 数据帧创建节点和关系
【发布时间】:2018-01-26 01:12:06
【问题描述】:

使用 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

现在我正在尝试使用 py2neo 创建(或更好地合并)一组从 pandas 数据帧到 Neo4j 数据库的节点和关系。想象一下我有一个像这样的数据框:

LABEL1 LABEL2
p1 n1
p2 n1
p3 n2
p4 n2

其中标签是列标题,属性是值。我想为我的数据框的每一行重现以下密码查询(以第一行为例):

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

我知道我可以将 py2neo 告诉 graph.run(query),甚至可以以相同的方式运行 LOAD CSV 密码脚本,但我想知道我是否可以遍历数据框并在 py2neo 中逐行应用上述查询。

【问题讨论】:

    标签: python pandas neo4j cypher py2neo


    【解决方案1】:

    您可以使用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']})
    

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

    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()
    

    通常我们可以在单个事务中批处理约 20k 数据库操作。

    【讨论】:

    • 我尝试做类似的事情。在 tx.commit() 处,代码失败 - AttributeError: 'Graph' object has no attribute 'commit'。问题可能是什么?这些是最初的导入行 - from py2neo import Graph, graph = Graph("bolt://localhost:7687", user="neo4j", password="xyz")
    • 您可能在引用tx 时忘记输入.begin()
    【解决方案2】:

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

    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()
    

    在我的例子中,我必须同时添加关系属性(参见下面的代码)。此外,我有 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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-27
      相关资源
      最近更新 更多