通过Py2neo在Neo4j中建立关系非常缓慢



我们在数据库中有5种不同类型的节点。最大的有~290k,最小的只有~3k。每个节点类型都有一个 id 字段,并且它们都已编制索引。我正在使用py2neo来建立关系,但它非常慢(~每秒插入2个关系(

我曾经pandas从关系 csv 中读取,迭代每一行以创建包装在事务中的关系。我尝试在一个事务中批量输出 10k 创建语句,但它似乎并没有提高很多速度。

下面是代码:

df = pd.read_csv(r"C:relationship.csv",dtype = datatype, skipinitialspace=True, usecols=fields)
df.fillna('',inplace=True)
def f(node_1 ,rel_type, node_2):
    try:
        tx = graph.begin()
        tx.evaluate('MATCH (a {node_id:$label1}),(b {node_id:$label2}) MERGE (a)-[r:'+rel_type+']->(b)',
                    parameters = {'label1': node_1, 'label2': node_2})
        tx.commit()
    except Exception as e:
        print(str(e))
for index, row in df.iterrows():
    if(index%1000000 == 0):
        print(index)
    try:
        f(row["node_1"],row["rel_type"],row["node_2"])
    except:
        print("error index: " + index)

有人可以帮助我在这里做错了什么。谢谢!

您声明有"5 种不同类型的节点"(在 neo4j 术语中,我将其解释为 5 个节点标签(。此外,您声明其id属性已编制索引。

但是您的f()函数根本不会生成使用标签的 Cypher 查询,也不会使用 id 属性。为了利用索引,Cypher 查询必须指定节点标签和id值。

由于目前没有有效的方法来参数化标签 执行MATCH ,以下版本的 f() 函数生成具有硬编码标签(以及硬编码关系类型(的 Cypher 查询:

def f(label_1, id_1, rel_type, label_2, id_2):
    try:
        tx = graph.begin()
        tx.evaluate(
                'MATCH' +
                '(a:' + label_1 + '{id:$id1}),' +
                '(b:' + label_2 + '{id:$id2}) ' +
                'MERGE (a)-[r:'+rel_type+']->(b)',
            parameters = {'id1': id_1, 'id2': id_2})
        tx.commit()
    except Exception as e:
        print(str(e))

还必须更改调用 f() 的代码,以传入标签名称和 abid值。希望您的df行将包含该数据(或足够的信息供您派生该数据(。

如果您的目标是获得更好的性能,那么您需要考虑加载这些内容的不同模式,即批处理。您当前正在为每个关系运行一个 Cypher MERGE 语句,并将其包装在单独的函数调用中。

通过查看每个事务或每个函数调用的多个语句来批处理这些语句将减少网络跃点数,并应提高性能。

最新更新