【问题标题】:Database creation takes to long in neo4j在 neo4j 中创建数据库需要很长时间
【发布时间】:2021-04-12 01:22:26
【问题描述】:

更新问题:

我是 neo4j 的新手,我正在尝试创建电影分级数据库。我有一个包含 100.000 个寄存器 (2,3 MB) 的文件,它代表用户对电影的评分;文件如下所示(此数据集来自 MovieLens):

dataset file

我正在使用 py2neo,并使用以下代码创建数据库:

data = pd.read_csv('ratings_small.csv')
def create_bipartite_graph(data):
#Indexes creation to perform the queries
    graph.run('''
        CREATE INDEX user_index IF NOT EXISTS FOR (u:User) ON (u.UserId)
    ''')
    graph.run('''
        CREATE INDEX movie_index IF NOT EXISTS FOR (m:Movie) ON (m.MovieId)
    ''')
    actual_user_node = None
    for index, row in data.iterrows():
        userID = int(row['userId'])
        movieID = int(row['movieId'])
        rating = row['rating']
        date = datetime.fromtimestamp(row['timestamp']).strftime("%m/%d/%Y, %H:%M:%S")

        #Creation nodes and relationships
        graph.run('''
            MERGE(u:User{UserId: $uID})
            MERGE(m:Movie{MovieId: $mID})
            CREATE (u)-[:RATED_MOVIE{rating: $r, date: $d}]->(m)
        ''', parameters = {'uID': userID, 'mID': movieID, 'r': rating, 'd': date})

问题在于那个小数据集,创建图表需要 2 个多小时。关于数据库创建时间大大减少的任何建议?

使用LOAD CSV

这是我在 neo4j 浏览器中执行的查询

EXPLAIN LOAD CSV With HEADERS FROM 'file:///ratings_small.csv' AS line FIELDTERMINATOR ',' 
MERGE(m:Movie{MovieId: toInteger(line.movieId)})
MERGE(u:User{UserId: toInteger(line.userId)})
CREATE (u)-[:RATED_MOVIE{rating:toFloat(line.rating)}]->(m)

这是个人资料计划: profile plan

【问题讨论】:

    标签: python database neo4j cypher py2neo


    【解决方案1】:

    每个graph run 调用不仅代表到服务器的完整往返,而且代表完全独立的事务。因此,像这样工作,在循环的每个循环中都有一个这样的调用,因此效率非常低。

    我建议改为查看批量数据操作 API: https://py2neo.readthedocs.io/en/stable/bulk/index.html

    【讨论】:

    • 这对我帮助很大,非常感谢。对于 100,000 个寄存器,只用了 25 秒。
    • 这更像是:)
    【解决方案2】:

    您是从 CSV 文件开始的,对吗?您可以使用 LOAD CSV 将其导入 Neo4j。使用您的 python 代码将 csv 放在 Neo4j 导入目录中。然后运行这个查询...

    LOAD CSV With HEADERS FROM 'file:///ratings_small.csv' AS line FIELDTERMINATOR ',' MERGE(m:Movie{MovieId: toInteger(line.mID)})
        ''', parameters = {'mID': toInteger(line.movieID),rating:toFloat(line.rating)})
    

    如果你想一次迭代 5000 行,你可以在开头添加这个

    Using periodic commit 5000 ....
    

    这应该运行得更快!

    【讨论】:

    • 对于该 MERGE,您需要在 :Movie(MovieId) 上建立索引,否则插入速度会一直减慢
    • 您可能希望在添加一个虚拟节点之前添加一个虚拟节点,创建一个索引以便合并运行得更快,然后在加载后删除虚拟节点。
    • @InverseFalcon 为了创建索引,我不需要创建所有节点吗?或者我可以创建一个虚拟节点作为 David cmets。
    • @DavidAStumpf 我会试试LOAD CSV 看看它是否有效,谢谢
    • @DavidAStumpf LOAD CSV 生成错误。我尝试这个 [1] 但仍然无法正常工作。 [1]:stackoverflow.com/questions/56573653/…
    猜你喜欢
    • 2021-08-07
    • 1970-01-01
    • 1970-01-01
    • 2014-04-13
    • 2013-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多