PostgreSQLのJSONB、->しか知らないところから少し掘り下げてみる

こんにちは、さるまりんです 🐒🔧

開発ではJSONを扱うことが増えてきましたね。

PostgreSQLにはJSONをそのまま扱えるデータ型として、JSON と JSONB があります。
JSONBでは専用の演算子が使えるなどの理由から、こちらを使うことが多いです。

それを使ってプログラムを書くとき、
とりあえずこんな書き方をしたことがありました。

SELECT data->'name' FROM users;

なんとなく値が取れるので、そのまま使っていました。

でも、

  • 文字列として扱いたいときは?
  • 条件検索はどうする?
  • パフォーマンスは大丈夫?

このあたりが、少しずつ気になってきます。

なので今回は、

「->しか知らない状態」から、JSONBを少し掘り下げてみる

という形で、実際に手を動かしながら整理していきます。

■ DockerでPostgreSQLを用意する

まずはすぐ試せる環境を用意します。

docker run --name postgres-jsonb \
  -e POSTGRES_PASSWORD=postgres \
  -p 5432:5432 \
  -d postgres:15

起動後、psqlで接続します。

docker exec -it postgres-jsonb psql -U postgres

■ テーブルを作る

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  data JSONB
);

JSONをそのまま入れるためのシンプルな構成です。

■ データを入れてみる

INSERT INTO users (data) VALUES
('{"name": "Chimpanzee", "age": 30, "city": "Tokyo"}'),
('{"name": "Orangutan", "age": 25, "city": "Osaka"}');

■ -> で値を取り出す

SELECT data->'name' FROM users;

ここでのポイントは、
JSONとして値が返るということです。

結果はこんな感じになります。

"Chimpanzee"
"Orangutan"

一見問題なさそうですが、次で少し違いが出てきます。

■ ->> で文字列として取り出す

SELECT data->>'name' FROM users;

こちらは、
テキスト(文字列)として返る形になります。

Chimpanzee
Orangutan

この違いがかなり重要です。

■ 条件検索してみる

例えば「Tokyoのさる」を取りたい場合。

SELECT *
FROM users
WHERE data->>'city' = 'Tokyo';

文字列として比較するので、->> を使います。

ここは最初に少し迷いやすいポイントです。

■ JSONとして比較する(@>)

SELECT *
FROM users
WHERE data @> '{"city": "Tokyo"}';

これは、
JSON同士で「含まれているか」を見る書き方です。

■ どちらを使うべきでしょう?

少し整理しておきます。

  • ->>
    → 値を取り出して比較(シンプル)
  • @>
    → JSON構造として一致を確認(柔軟)

実務では、

単純な条件なら ->>
複数条件・構造を見るなら @>

という使い分けになることが多いです。

■ インデックスを貼ってみる

JSONBは便利ですが、そのままだと遅くなることがあります。

CREATE INDEX idx_users_data ON users USING GIN (data);

これで、@> の検索が速くなるようになります。

■ ちょっとだけ踏み込んで

実際に使っていると、こんな場面があると思います。

JSONBはとても便利ですが、使いどころは少し考える必要があります。

例えば:

  • スキーマが固定できないデータ
  • 外部APIのレスポンス保存
  • ログやイベントデータ

こういった場面ではとても相性が良いです。

一方で、

頻繁に条件検索する項目はカラムに持つ

という判断も大事になります。

JSON構造のまま持つと、検索時のパフォーマンスに影響が出ることもあるため、このあたりの設計は重要です。

■ まとめ

今回は、

  • -> と ->> の違い
  • 条件検索の書き方
  • @> の使い方
  • インデックス(GIN)

このあたりを触ってみました。

最初は「なんとなく使っている」状態でも、

少しずつ理解していくと、
どこで使うかを判断できるようになると思います。

■ おわりに

JSONBは触ってみると楽しい機能です。

実際の開発では、REST APIのリクエストやレスポンスをそのまま保存することも多く、使う機会は増えていると感じています。

今回の内容も、実際に動かしながら試してみると、
「なんとなく」が一歩進む感覚があると思います。

「ここどうなるんだろう?」と思ったところがあれば、
そこが次に理解が進むポイントかもしれません。

知りたいと思う気持ちを大切に。

読んでくださってありがとうございました。
それではまた!