はじめに
本記事では,私がneo4jのMERGE句の利用でつまずいたので,備忘録とカレンダーの作成がてらMERGE句の使い方をまとめていこうと思います
MERGE関連の公式ドキュメント
MERGE句とは
MERGE句は,ノードやリレージョンが存在するときは上書きを,存在しない時は新規に作成を行ってくれる構文になります
基本的な使い方
MERGE (n:Label {name: $value})
ON CREATE SET n.created = timestamp()
ON MATCH SET
n.counter = coalesce(n.counter, 0) + 1,
n.accessTime = timestamp()
MERGEを利用しない場合
作成時
CREATE (n:Label {name: $value, created: timestamp()}
更新時
MATCH (n:Label)
WHERE n.name = $value
SET
n.counter = coalesce(n.counter, 0) + 1,
n.accessTime = timestamp()
or
MATCH (n:Label {name: $value})
SET
n.counter = coalesce(n.counter, 0) + 1,
n.accessTime = timestamp()
プログラムから利用することを考えると,場合分けをしないで使えるMERGE句のありがたみが分かると思います
発生した問題
現在作成中のプログラムは,ユーザーの関係を管理するためneo4jを採用しました.Userの持つプロパティは一部省略しますが以下のようになっています
-
id
:ユーザーID ユニーク -
displayName
:表示名 -
createdAt
:Userの作成時刻
idはユニークですので,neo4jに以下の設定を行いました
CREATE CONSTRAINT unique_user_id IF NOT EXISTS
FOR (u:User)
REQUIRE u.id IS UNIQUE
ここで,プログラム側の実行時に公式アカウントを作成済みでなければ作成する機能が欲しかったので,以下のようなcypherを実行するプログラムの作成を行いました
MERGE (:User {
id: "official",
displayName: "公式",
createdAt: datetime()
})
一回目の実行では正常に成功し,以下のようなUserが作成されました
{
"id": "official",
"displayName": "公式",
"createdAt": "2023-12-01T00:00:00Z"
}
期待通りの結果が得られ,ヨシッとこの時までは思っていました.が,次の機能を開発し,サーバーを再起動すると以下のエラーが出るようになりました.
Node(0) already exists with label `User` and property `id` = 'official'
このエラーはユニーク制約に引っかかって出力されるエラーになります.テストのために以下のようなコードを作成し,検証を行いました
MERGE (:Test {prop: "test"})
しかし,こちらのコードでは何回実行してもエラーにはなりませんでした.ここで私は,「MERGE句の内部処理で一回同じidのノードを作成してしまっているのではないか」とあたりをつけてバグの解決策を調べ始めました.自分のプログラムは絶対あってるって思っちゃうよね
しかし,neo4jの公式やライブラリのissueをみても解決せず...ここでやっと自分のプログラムが間違っているのではないかと考え始めました.
解決
よくよく考えてみると,MERGE句はどこで新規か上書きかの判別を行っているのかといった疑問が浮かびました.調べた結果が以下になります(唐突)
MERGE (n:Label {ここに一致条件を列挙})
ON CREATE SET
ここに新規作成時に設定するプロパティを列挙
ON MATCH SET
ここに更新時に設定するプロパティを列挙
私のプログラムを修正すると以下のようになります
MERGE (u:User {id: "official"})
ON CREATE SET
u.displayName = "公式",
u.createdAt = datetime()
})
まとめ
今回,MERGE句の利用でつまずいたので,MERGE句の使い方についてまとめてみました.直接的にエラーで指摘されないと,自分のコードを間違ってると思えないのは悪い癖ですね.私失敗しないのでって言えるエンジニアになりたい...(先は長そう)
記事にまとめてみると,その時自分は何を考えてそうしたかや,どうするべきだったか反省出来て良かったです.ゆめみの24卒カレンダーに参加しているので,また何かしら問題に詰まったら,復習がてら記事を書いてこうと思います.では!