【问题标题】:Optimizing py2neo's cypher insertion优化 py2neo 的密码插入
【发布时间】:2015-06-03 00:22:47
【问题描述】:

我正在使用 py2neo 导入数十万个节点。我创建了一个 defaultdict 来将社区映射到城市。一个动机是更有效地导入这些使用Neo4j's load tool 失败的关系。

因为batch documentation 建议避免使用它,所以我偏离了this post 的OP 之类的实现。相反,文档建议我使用 Cypher。但是,我喜欢能够从我创建的 defaultdict 创建节点。另外,正如first link 演示的那样,我发现导入这些信息太困难了。

为了降低导入速度,我应该创建一个Cypher transaction(并且每 10,00 提交一次)而不是下面的循环吗?

for city_name, neighborhood_names in city_neighborhood_map.iteritems():
     city_node = graph.find_one(label="City", property_key="Name", property_value=city_name)
         for neighborhood_name in neighborhood_names:
              neighborhood_node = Node("Neighborhood", Name=neighborhood_name)
              rel = Relationship(neighborhood_node, "IN", city_node)
              graph.create(rel)

我遇到了超时,当我执行以下操作时它似乎很慢。即使我将事务分解为每 1000 个社区提交一次,它的处理速度仍然非常缓慢。

tx = graph.cypher.begin()
statement = "MERGE (city {Name:{City_Name}}) CREATE (neighborhood { Name : {Neighborhood_Name}}) CREATE (neighborhood)-[:IN]->(city)"
for city_name, neighborhood_names in city_neighborhood_map.iteritems():
    for neighborhood_name in neighborhood_names:
        tx.append(statement, {"City_Name": city_name, "Neighborhood_Name": neighborhood_name})
tx.commit()

保存指向每个城市的指针会很棒,所以我不需要每次合并时都查找它。

【问题讨论】:

    标签: python neo4j graph-databases py2neo


    【解决方案1】:

    在两次运行中执行此操作可能会更快,即首先CREATE所有节点具有唯一约束(应该非常快),然后CREATE第二轮中的关系。

    首先使用约束,使用标签CityNeighborhood,稍后使用更快的MATCH

    graph.schema.create_uniqueness_constraint('City', 'Name')
    graph.schema.create_uniqueness_constraint('Neighborhood', 'Name')
    

    创建所有节点:

    tx = graph.cypher.begin()
    
    statement = "CREATE (:City {Name: {name}})"
    for city_name in city_neighborhood_map.keys():
        tx.append(statement, {"name": city_name})
    
    statement = "CREATE (:Neighborhood {Name: {name}})"
    for neighborhood_name in neighborhood_names: # get all neighborhood names for this
        tx.append(statement, {name: neighborhood_name})
    
    tx.commit()
    

    现在的关系应该很快(由于约束/索引,很快MATCH):

    tx = graph.cypher.begin()
    statement = "MATCH (city:City {Name: {City_Name}}), MATCH (n:Neighborhood {Name: {Neighborhood_Name}}) CREATE (n)-[:IN]->(city)"
    for city_name, neighborhood_names in city_neighborhood_map.iteritems():
        for neighborhood_name in neighborhood_names:
            tx.append(statement, {"City_Name": city_name, "Neighborhood_Name": neighborhood_name})
    
    tx.commit()
    

    【讨论】:

    • 正如我在此链接 (stackoverflow.com/questions/30444845/…) 中提到的,社区不是唯一的,因此我无法创建唯一性约束。因此,我不能单独创建城市和社区,需要在关系上合并。
    • 为什么它们不是唯一的?只需按名称添加它们,如果一个社区位于多个城市,则城市-社区关系包含该信息。
    • 因为一个名为“Downtown”的社区可以出现在多个城市中。我认为应该有一个独特的节点来代表每个名为“Downtown”的社区。你同意这个结构吗?
    • 取决于查询。为什么不只是市中心和城市与市中心之间的纽带?
    • 因为每个市中心都有独特的信息(如人口规模)。我认为每个市中心都有一个不同的节点会更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多