# Neo4jの機能と実践的な使い方
♻️ 「なければ作る、あれば更新する」——イベントストリームを何度流しても重複ノードを生まない冪等な書き込みは、`MERGE` 一文で実現できます。
🏷️ タイトル: CREATE / MERGE / SET / DELETE
🔗 URL:
📘 概要
`MERGE` は、パターンが存在すればマッチして束縛し、なければ作成して束縛する upsert クラウズです。`MATCH` と `CREATE` を一体化し、過去にデータが在ったかどうかで条件分岐できます。日次バッチやストリーム取り込みの冪等化に不可欠です。
⚙️ 機能の説明
・全体一致か全体作成か: `MERGE` はパターン全体に対して「すべてマッチ」か「すべて作成」のどちらかで、既存パターンを部分的に再利用しません。部分的に扱いたい場合は `MERGE` を複数に分解します。
・`ON CREATE SET` / `ON MATCH SET`: 作成時だけ・マッチ時だけ実行されるプロパティ設定です。作成時刻の刻印やアクセス回数のインクリメントに使えます。両方を同時に書けます。
・リレーションシップの `MERGE`: 少なくとも片方のノードが束縛済みである必要があります。無向 `-[r:KNOWS]-` は双方向で探してから左→右で作成します。
・制約との連動: 一意制約があると `MERGE` は競合検知を行い、重複生成を防ぎます。性能上もラベル/プロパティへのインデックス作成が強く推奨されます(無いと毎回フルスキャン)。
🛠️ 実践的な使い方
イベントストリームの冪等な upsert 例です。
```cypher
MERGE (u:User {id: row.userId})
MERGE (p:Page {url: row.url})
MERGE (u)-[v:VIEWED]->(p)
ON CREATE SET v.count = 1
ON MATCH SET v.count = v.count + 1
```
派生ノードを重複なく作る定番パターンです。
```cypher
MATCH (person:Person)
MERGE (loc:Location {name: person.bornIn})
MERGE (person)-[r:BORN_IN]->(loc)
ON CREATE SET r.createdAt = timestamp()
```
💡 ユースケース
・クリックストリーム/IoTイベントの取り込みで、同一ユーザー・ページを一意化しながらカウントを積み上げる。
・複数パイプラインからマスタを書き込んでもエンティティが二重化しない取り込み基盤。
⚠️ 注意点
・`MERGE` のキーには一意制約を併用するのが鉄則です。制約が無いと並行実行で一瞬の重複が生じ得ます(制約は最終的整合のみ保証)。
・`MERGE` のプロパティに `null` は使えません。条件付き設定は後段の `SET` で行います。
・同一 `MERGE` 内で作成中ノードの値を相互参照できません。先に `MATCH` するか `SET` に分けます。
・`DELETE` はリレーションシップ付きノードに失敗します。`DETACH DELETE` を使います。
#
Neo4j# #
Cypher#