2017-10-04 6 views
2

Neo4jを初めて使用しました。基本についてわからないことがあります。Neo4j、Cypherコマンドで一括読み込み

私はJavaで多くのオブジェクトを持っており、それらを使ってJavaドライバとCypherを使ってNeo4jグラフを生成したいと考えています。私のコードは次のように機能します。

// nodes 
for (Person person: persons) 
    session.run (String.format ( 
    "CREATE (:Person { id: '%s', name: \"%s\", surname: \"%s\" })", 
    person.getId(), person.getName(), person.getSurname() 
)); 

// relations 
session.run ("CREATE INDEX ON :Person(id)"); 

for (Friendship friendship: friendships) 
    session.run (String.format ( 
    "MATCH (from:Person { id: '%s' }), (to:Person { id: '%s' })\n" + 
    "CREATE (from)-:KNOWS->(to)\n", 
    friendship.getFrom().getId(), 
    friendship.getTo().getId() 
)); 

(私はダースのノードの種類を持っており、関係型の同じ数のおよそ原因確かに、それは、少し複雑です)。

これは非常に遅く、300kノードと1Mリレーションをロードするのに1時間以上かかるようです(かなり高速のMacBookProではNeo4jで12/16GBのRAMを使う)。

私は間違ったやり方をしていますか?代わりにbatch inserterを使用する必要がありますか? (私はネットワーク経由でgraphDBにアクセスできる方が好きです)。 1つのトランザクションに複数の挿入をグループ化することで何かを得ることはできますか? (ドキュメントからは、トランザクションはロールバックと分離の必要性にのみ役立つと思われます)。

答えて

0

私はPythonでNeo4jから来ていますが、ここでの問題はあなたのCypherコマンドにあると思います。私には2つの提案があります。

エッジを個別にマッチさせるほうが速い場合があります。私のプリミティブのベンチマークでは、私はこの(:このベンチマークは疑わしいですEDIT):24msと15msの対の違いを参照してください

MATCH (from:Person { id: '%s' }) 
MATCH (to:Person { id: '%s' }) 
CREATE (from)-:KNOWS->(to) 

別のオプションは、UNWINDを使用することです。私はBOLTインターフェイスでこれを使用して、より少ないトランザクションを送信しますが、バッチインサータは使用しません。私がここにコピーしているPythonの実装を許してください。うまくいけば、それを変換するJavascript Neo4j Driverのドキュメントと一緒に見ることができればと思います。

payload = {"list":[{"a":"Name1","b":"Name2"},{"a":"Name3","b":"Name4"}]} 

statement = "UNWIND {list} AS d " 
statement += "MATCH (A:Person {name: d.a}) " 
statement += "MATCH (B:Person {name: d.b}) " 
statement += "MERGE (A)-[:KNOWS]-(B) " 

tx = session.begin_transaction() 
tx.run(statement,payload) 
tx.commit() 
+0

ありがとうございますが、私のケースではうまくいかないと思います。私のアプリケーションが内部グラフ(ハッシュマップを使用して)を3分未満で埋めることを考えれば、24〜15msは大きく異なりますが、Neo4jは同じように年月を要します。それは正しいことはできません、それは多かれ少なかれ同じようにする必要があります。 WINDについては、リストをパラメータとして送信すると、最終的には非常に多くのノードとエッジがあることを考慮すると、大きすぎるクエリに変わると思います。 – zakmck

+0

私のベンチマークはオフかもしれませんが、少なくともUNWINDを試してみることを強くお勧めします。あなたのペイロードリストはあなたのデータのすべてである必要はありません。あなたはそれをチャンクすることができます(私は実際にはそうですが、上記のコードではありません)。ペイロードのサイズが〜100kで、N個のトランザクションでエッジを埋めることができれば、N * 100k個の個別トランザクションに比べて時間が節約できます。 – sjc

+0

感謝@sjc、私はUNWINDのポイントを参照してください、私はそれを試してみましょう。 – zakmck

0

私はこれについて私の経験を報告する価値があると思います。

私は@sjcの提案に従い、UNWINDで試しました。しかし、Cypherではパラメータ化されたノードラベルやリレーションタイプ(およびラベルとリレーションタイプが12個あります)が許可されていないため、単純ではありませんでした。しかし結局は、すべての可能なタイプをループして、UNWINDチャンクごとに十分なアイテム(約1000)を送信することができました。

UNWINDを使用しているコードは、私の意見では十分に速いですが、十分に速いわけではありません(まともなPCで数百万のノード、数億のノードではそれほど良くないはずです)。

インサータコンポーネントは、HTTPアクセスをダウンさせる必要がありますが、Lucene 5.4への依存性には多くの問題がありましたが、 Lucene 6を使用するアプリケーション(データを生成する)の内部で使用すると、classpathで5.4と6を単に交換するときにひどいことが起こりました。私はそれの周りにthere is some mechanism to make this possibleを持っていますが、それは簡単には思わしくないと確かにあまりよく文書化されていません。

このような基本的な操作を効率的に実行するためには、このようなトラブルはすべて間違いありませんでした。

関連する問題