2016-10-10 16 views
0

Neo4jとPythonが初めてで、IPythonを使ってテストデータベースにノードとリレーションシップを設定しようとしています。私はpy2neo v 3.1.2を使用しています。私が取り組もうとしている問題は、単語countをプロパティとするリンクを介して文章IDを含む単語の集合にグラフの集合を表すことです。Neo4j経由のグラフ作成に時間がかかりすぎる

String(num)とWord(val)の両方に関連するNeo4j制約を追加しました。関連するコードをここに与えられます。

from py2neo import Graph, Node, Path 
import re 
graph = Graph("http://neo4j:[email protected]:7474/db/data/")  
f1 = open("test.txt", "r") 
cnt = 0 
for line in f1: 
    cnt = cnt+1 
    line=line.lower() 
    line = re.sub(r'[^\w\s]','',line) 
    wordlist = line.split() 
    lgth = len(wordlist) 
    wordfreq = [wordlist.count(w) for w in wordlist] 
    dct = dict(zip(wordlist,wordfreq)) 
    str = Node("String", num=cnt, length = lgth) 
    graph.merge(str) 
    for k, v in dct.items(): 
     wrd = Node("Word", val=k) 
     graph.merge(wrd) 
     property_dict = {"wrdcnt": v} 
     relate = Path(str, ("CONTAINS",property_dict),wrd) 
     graph.merge(relate) 

1000行の小さなコレクションはのNeo4jのグラフのように移入するために約10分かかります。私は私のPythonコードで何かを間違ってやっていると確信して、同じことが大幅にスピードアップすることができます。意味のある洞察に感謝します。

+0

あなたの解析だけをベンチマークしましたか?また、あなたはかなりの量のマージを行っています。おそらく、あなたの質問を編集して、インポート時にあなたが実行しているコアのCypherクエリを表示してください。 –

+0

私は解析をベンチマークしました。pythonコードがサブ秒でジップします – user6948456

答えて

0

各文にの単語1つにつきと2つのクエリを実行しています。それらの便利な方法を使用してオーバーヘッドの膨大な量が発生しているため、時間がかかります。あなたはパラメータを使用している場合帰り文ごとに単一のクエリにカットし、サイファーに作業の多くを置くことができます。

from collections import Counter 
from string import maketrans, punctuation 
no_punc = maketrans(punctuation, ' ' * len(punctuation)) 
with open('test.txt', 'r') as f1: 
    for ct, line in enumerate(f1): 
     line = line.lower().translate(no_punc).split() 
     length = len(line) 
     dct = Counter(line) 
     graph.run(''' 
      MERGE (s:Sentence { id:{count}, length: {s_length} }) 
      WITH s 
      UNWIND keys({dct}) AS word 
      MERGE (w:Word { id: word }) 
      MERGE (s) - [:CONTAINS {wrdcnt: {dct}[word] }] -> (w)''', 
      parameters={'dct': dct, 's_length': length, 'count': ct}) 

ラビット:これは、1つのクエリで行われ、全体の事です。それは可愛いわけではありませんが、潜在的に最速です。また、どちらの場合でも:Sentence(id):Word(id)にインデックスがあることを確認してください。両方のスピードが劇的に向上します。

from collections import Counter 
from string import maketrans, punctuation 
no_punc = maketrans(punctuation, ' ' * len(punctuation)) 
params = [] 
with open('test.txt', 'r') as f1: 
    for ct, line in enumerate(f1): 
     line = line.lower().translate(no_punc).split() 
     length = len(line) 
     dct = Counter(line) 
     params.append({'dct': dct, 's_length': length, 'count': ct}) 
graph.run(''' 
    UNWIND {params} AS param 
    WITH param['dct'] AS dct, param['count'] AS ct, param['s_length'] AS s_length 
    MERGE (s:Sentence { id: ct, length: s_length }) 
    WITH s, dct 
    UNWIND keys(dct) AS word 
    MERGE (w:Word { id: word }) 
    MERGE (s) - [:CONTAINS {wrdcnt: dct[word] }] -> (w)''', 
    parameters={'params': params}) 
+0

次のエラーがIPythonでスローされます - CypherSyntaxError:MERGEとUNWINDの間にWITHが必要です – user6948456

+0

ええ、上記の修正済みです。 –

+0

ありがとうございます、これはプログラムをスピードアップしました。今は1000行(6334ノード、21777リレーション)のサブ2分です。しかしこれが改善できるかどうか疑問に思う。以前、5分以内に50万ノードのCSV形式をインポートしようとしました。ただし、現在のタスクはテキスト指向のものです – user6948456

関連する問題