【実務・中級編】 JSONB演算子 – PostgreSQL

PostgreSQLのJSONBを使いこなせ!現場で差がつく演算子テクニック完全ガイド

やあ。PostgreSQLのJSONB、使ってる?

最近のバックエンド開発だと、「とりあえずカラムをJSONBにしておこう」っていう設計、よく見るよね。柔軟だし、スキーマ変更に怯えなくて済むから便利なんだけど……正直、「適当に突っ込んで、いざ検索するときに沼る」という経験、一度はあるんじゃないかな。

JSONBはただのデータの入れ物じゃない。PostgreSQLという強力なエンジンの上で、リレーショナルな世界と柔軟なドキュメントの世界をつなぐ強力な武器なんだ。今日は、現場で本当に役立つJSONB演算子について、教科書には書いていない「使いどころ」を交えて解説するよ。

—

1. 「探す」ための演算子:包含と存在

JSONBを扱ううえで、まず押さえるべきは「特定のデータが含まれているか」を確認する演算子たちだ。

包含演算子 `@>` と `

これは「このJSON構造を一部として含んでいるか?」をチェックする、いわばJSONB界の切り札だ。

— “tags”の中に”golang”が含まれているレコードを探す
SELECT FROM products WHERE attributes @> ‘{“tags”: [“golang”]}’;

【現場の視点】
`@>` は非常に強力で、適切にGINインデックスを貼れば爆速で動作する。これを知らずに `->>` で文字列変換してから `LIKE` 検索したりしてないよね? それは性能をドブに捨てているのと同じだよ。

存在演算子 `?`, `?|`, `?&`

これは「トップレベルのキー」が存在するかをチェックする。

  • `?`: 指定したキーがあるか
  • `?|`: 指定したキーの「どれか」があるか
  • `?&`: 指定したキーの「すべて」があるか

— “status”キーが存在するレコード
SELECT FROM orders WHERE data ? ‘status’;

— “created_at” または “updated_at” キーが存在するレコード
SELECT FROM logs WHERE data ?| array[‘created_at’, ‘updated_at’];

—

2. 「加工・結合」する演算子:連結と削除

JSONBを更新する際、アプリケーション側で全部書き換えて `UPDATE` していちゃダメだ。データベース側でスマートにやろう。

連結演算子 `||`

JSONB同士をマージする。設定の更新なんかでめちゃくちゃ使う。

— 元のデータに新しいフィールドを追加・更新する
UPDATE settings
SET data = data || ‘{“theme”: “dark”, “notifications”: true}’
WHERE id = 1;

削除演算子 `-` と `#-`

不要になったキーを消すときや、深い階層の値を消すときに使う。

— “temp_key” というキーを削除
UPDATE logs SET data = data – ‘temp_key’;

— ネストされた値を削除 (path指定)
UPDATE logs SET data = data #- ‘{user, metadata, old_id}’;

【現場の視点】
`#-` でパスを指定して消す書き方は、最初は直感に反するかもしれないけど、慣れると「あ、ここ消したいな」という時に一発で書けるから非常に重宝するよ。

—

3. 「取り出す」ための演算子:抽出

最後に、値を取り出す `->` と `->>` だ。

  • `->`: JSONBオブジェクトとして取り出す(さらに演算が続けられる)
  • `->>`: テキストとして取り出す(ソートや比較演算に使いたいとき)

— 値を数値として比較するなら、一度 ->> で文字列にしてからキャストする
SELECT FROM users WHERE (data->>’age’)::int > 20;

— ネストされたオブジェクトをさらに操作する
SELECT data->’profile’->>’name’ FROM users;

—

先輩からのアドバイス:パフォーマンスの落とし穴

最後に一つだけ、どうしても伝えておきたいことがある。

「JSONBを使っているからといって、すべてをJSONBで解決しようとしないこと」

JSONBは便利だけど、リレーショナルな正規化には勝てない。

  • 頻繁に検索条件にする値
  • 結合(JOIN)のキーにする値
  • 計算が必要な数値データ

これらは素直にカラムを分けるか、`GENERATED COLUMN`(生成列)を使ってインデックスを貼るのが鉄則だ。JSONBは「構造が可変なメタデータ」のための場所であって、テーブル設計をサボるための隠れ家じゃないからね。

最初は少し難しく感じるかもしれないけど、PostgreSQLのJSONBを使いこなせると、設計の幅がグッと広がるはずだよ。また何か詰まったら、いつでも聞きに来てくれ。

さて、今日はここまで。良いSQLライフを!

コメント

タイトルとURLをコピーしました