2016-11-09 18 views
1

我試圖導入lastfm360K數據庫到數據庫Neo4j的。我先插入所有用戶節點沒有任何問題與下面的代碼掛起,而將數據導入的Neo4j與Python

import re 
from datetime import datetime 
from elasticsearch import Elasticsearch 
import certifi 
from neo4j.v1 import GraphDatabase, basic_auth 

driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "pass")) 
session = driver.session() 

with open("/Users/inanc/Documents/Software/lastfm-dataset-360K/usersha1-profile.tsv" , 'r') as userFile: 
    #first_line = userFile.readline() 
    linenum = 0 
    for line in userFile: 
     linenum = linenum + 1 
     if linenum % 1000 == 0: 
      print(linenum) 
     lineStrip = line.rstrip().split("\t") 
     tempDict = {} 
     tempDict["user_id"] = lineStrip[0] 
     if len(lineStrip) > 1: 
      tempDict["gender"] = lineStrip[1] 
      if lineStrip[2] != "": 
       tempDict["age"] = int(lineStrip[2]) 
      tempDict["country"] = lineStrip[3] 
      tempDict["signup"] = lineStrip[4] 
     session.run("CREATE (a:Person {dict})", {"dict": tempDict}) 


session.close() 

然後我要添加藝術家節點和關係與用戶如下

import re 
from datetime import datetime 
from elasticsearch import Elasticsearch 
import certifi 
from neo4j.v1 import GraphDatabase, basic_auth 

driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "pass")) 
session = driver.session() 

linenum = 0 
with open("/Users/inanc/Documents/Software/lastfm-dataset-360K/usersha1-artmbid-artname-plays.tsv" , 'r') as songFile: 
    for line in songFile: 
     linenum = linenum + 1 
     if linenum % 10000 == 0: 
      print(linenum) 
     lineStrip = line.rstrip().split("\t") 
     if len(lineStrip) == 4: 
      #print(line) 
      user_id = lineStrip[0] 
      musicbrainz_artistid = lineStrip[1] 
      artist_name = lineStrip[2] 
      plays = 1 
      if lineStrip[3] != "": 
       plays = int(lineStrip[3]) 

      session.run("MERGE (a:Artist {artist_name: {artist_name}})", {"artist_name": artist_name}) 
      session.run("MATCH (p:Person {user_id: {user_id}}), (a:Artist {artist_name: {artist_name}}) CREATE (p)-[:LIKES {times: {plays}}]->(a)", {"user_id": user_id, "artist_name": artist_name, "plays": plays}) 

session.close() 

它開始這樣做沒有任何錯誤(這它的速度非常慢,需要花費數小時),但是在某個時間點之後它會掛起(例如幾百萬行之後)。即使我的python腳本掛起,我仍然可以通過瀏覽器查詢。

我唯一的約束是

create constraint on (p:Person) assert p.user_id is unique; 
create constraint on (a:Artist) assert a.artist_name is unique; 

我使用了一臺Macbook與8GB的內存Neo4j的3.0.7。我也使用neo4j官方支持的python driver

任何幫助將不勝感激!

回答

1

每次調用session.run()執行以下操作:

  • 開始事務。
  • 執行傳遞給run()的Cypher語句。
  • 提交(或回滾)事務。

在你的情況,你實際上是使每個輸入線 session.run()電話。不僅如此,在第二次調用中的Cypher聲明必須在第一次調用中由Cypher獲得MATCH節點Artist

由於您的輸入文件中有1750萬線,這意味着你正在創建/提交/關閉3500萬周的交易。另外,您正在執行1750萬次不必要的MATCH操作。這是非常昂貴的極其,並且也有可能導致駕駛員有時絆倒。

建議:

  1. 你應該在同一事務中批處理多個操作。例如,如果您在每次交易中批量處理10K個操作,則1750萬個輸入行只需要1750個事務。

  2. 你應該兩個暗號報表合併成一個。

例如,你應該,如果你改變了你的代碼,以便得到更好的結果:

  • 生成具有10K元素,每一批次list陣列參數,該參數(如果美化打印)將是這樣的:

    {"list": 
        [ 
        {"id": 1, "name": 'aaa', "plays": 3}, 
        {"id": 2, "name": 'bbb', "plays": 2}, 
        {"id": 3, "name": 'ccc', "plays": 3}, 
        ... 
        {"id": 10000, "name": 'xyz', "plays": 7} 
        ] 
    } 
    
  • 使用以下的Cypher聲明:

    UNWIND {list} AS d 
    MATCH (p:Person {user_id: d.id}) 
    MERGE (a:Artist {artist_name: d.name}) 
    MERGE (p)-[:LIKES {times: d.plays}]->(a) 
    
  • 使用上述Cypher語句和參數調用session.run()(每10K輸入行一次)。

+0

Omg,你說得對!它像一個魅力一樣工作!它沒有掛起,只花了28分鐘來插入所有的節點和關係。非常感謝! –