Cypher Tips

February 16, 2022

Cypher Tips


Delete Huge node with all its relationships


例えば、あるノードだけ削除したいとします。 一般的にはこのようなCypherを書きます。 数千件のレベルだとこれでノードとそれに紐づいているリレーションシップが削除されます。 ところが、数百万件だと一度に処理しようとするので処理は終わらないしメモリーもオーバーフローします。

MATCH (n:SomeNode) DETACH DELETE n;

そこで、APOCのライブラリーを使ってバッチサイズを設定し小さな単位で処理します。 parallelはメモリーによって選択してください。 これで、億単位の削除も小さなメモリーで高速に処理できます。

CALL apoc.periodic.iterate(
  "MATCH (n:SomeNode) RETURN n",
  "DETACH DELETE n",
  {batchSize:10000, parallel:true});

LOAD CSV with Transaction


CSVからNeo4jにデータをロードする時にはLOAD CSVを使います。 LOAD CSVはデータベースがアクティブな時でも使えるコマンドです。

これは、ヘッダーが無いCSVの例です。

LOAD CSV FROM 'file:///artists.csv' AS line
  CREATE (:Artist {name: line[1], year: toInteger(line[2])})

件数が多くなるとトランザクションを使うと処理はとっても早くなります。 Neo4j 4.3まではこのような書き方です。

:auto USING PERIODIC COMMIT 2000
LOAD CSV FROM 'file:///artists.csv' AS line
  CREATE (:Artist {name: line[1], year: toInteger(line[2])})

Neo4j 4.4からは CALL TRANSACTIONS が使えます。

:auto LOAD CSV FROM 'file:///artists.csv' AS line
CALL {
  WITH line
  CREATE (:Artist {name: line[1], year: toInteger(line[2])})
} IN TRANSACTIONS OF 2000 ROWS

Simple existential subquery


WHEREの条件にリレーションシップを含める時の書き方です。

MATCH (:Node {name:'a'})-[:REL1|REL2*..10]->(n:Node)
WHERE (n)-[:REL2]->(:Node)
RETURN n;

上記は分かりやすいのですが、将来的に変わるということなので EXISTSを使って書き換えます。

MATCH (:Node {name:'a'})-[:REL1|REL2*..10]->(n:Node)
WHERE EXISTS {
  MATCH (n)-[:REL2]->(:Node)
}
RETURN n;

Profile picture

Written by Koji Annoura who lives and works in Fukuoka Japan. You should follow them on Twitter