2016-11-21 8 views
3

Neo4jの関係プロパティを効率的に一括更新するのに苦労しています。目的は、私は、単一のサイファーステートメント、Neo4jでのパフォーマンスの一括更新の関係プロパティ

UNWIND {rows} AS row 
MATCH (s:Entity) WHERE s.uuid = row.source 
MATCH (t:Entity) WHERE t.uuid = row.target 
MATCH (s)-[r:CONSUMED]->(t) 
SET r += row.properties 

1,000と処理のバッチにチャンクが千個のノードの各バッチは、約60秒かかり〜50万関係(おおよそ3特性を有する各々)を更新することです。私が以前に実行したすなわち:EntityラベルのUUIDプロパティのインデックス、関係をマッチングはクエリプランごとの超効率的であることを意味

CREATE INDEX ON :Entity(uuid) 

enter image description here

ありますが存在します合計6回のヒットとなり、照会は〜150ミリ秒で実行されます。私も各試合は一つだけの要素を返すことが保証さUUID財産上の一意性制約を追加しました、

CREATE CONSTRAINT ON (n:Entity) ASSERT n.uuid IS UNIQUE 

誰もが、私はさらにそれがのNeo4jを取っている理由を理解するために関係を処理する限り、これをデバッグする方法を知っています?

私はノードを更新するのに似たロジックを使用していますが、それよりもはるかに速く、より多くのメタデータが関連付けられています。

参考までに、私はNeo4j 3.0.3、py2neo、Boltを使用しています。 Pythonコードブロックの形式である、

for chunk in chunker(relationships): # 1,000 relationships per chunk 
    with graph.begin() as tx: 
     statement = """ 
      UNWIND {rows} AS row 
      MATCH (s:Entity) WHERE s.uuid = row.source 
      MATCH (t:Entity) WHERE t.uuid = row.target 
      MATCH (s)-[r:CONSUMED]->(t) 
      SET r += row.properties 
      """ 

      rows = [] 

      for rel in chunk: 
       rows.append({ 
        'properties': dict(rel), 
        'source': rel.start_node()['uuid'], 
        'target': rel.end_node()['uuid'], 
       }) 

      tx.run(statement, rows=rows) 

答えて

2

は、このクエリを実行してください。

UNWIND {rows} AS row 
WITH row.source as source, row.target as target, row 
MATCH (s:Entity {uuid:source}) 
USING INDEX s:Entity(uuid) 
WITH * WHERE true 
MATCH (t:Entity {uuid:target}) 
USING INDEX t:Entity(uuid) 
MATCH (s)-[r:CONSUMED]->(t) 
SET r += row.properties; 

それは両方Entityノードと、より多くなければならないExpand(Into)オペレータのインデックス・ルックアップを強制的にindex hintsを使用しますクエリプランで示されたExpand(All)およびFilter演算子よりもパフォーマンスが良いです。

0

@ william-lyon私はWITH * WHERE true句が必要かどうか疑問に思っていましたか?私は質問の理由、すなわち、DBの数が4から8に増加に当たることである

PROFILE 
MATCH (s:Entity {uuid:row.source}) 
USING INDEX s:Entity(uuid) 
MATCH (t:Entity {uuid:row.target}) 
USING INDEX t:Entity(uuid) 
MATCH (s)-[r:CONSUMED]->(t) 

戻り

PROFILE 
MATCH (s:Entity {uuid:row.source}) 
USING INDEX s:Entity(uuid) 
WITH * WHERE true 
MATCH (t:Entity {uuid:row.target}) 
USING INDEX t:Entity(uuid) 
MATCH (s)-[r:CONSUMED]->(t) 

一方戻り

注意:ヒントを使用すると、DBヒット数が6から4に減少します。コンテキストの場合、すべてのノードに:Entityラベルが付いていますが、複数のノードラベル(およびインデックス)があります。