こんにちは、さるまりんです 🐒🔧
開発では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のリクエストやレスポンスをそのまま保存することも多く、使う機会は増えていると感じています。
今回の内容も、実際に動かしながら試してみると、
「なんとなく」が一歩進む感覚があると思います。
「ここどうなるんだろう?」と思ったところがあれば、
そこが次に理解が進むポイントかもしれません。
知りたいと思う気持ちを大切に。
読んでくださってありがとうございました。
それではまた!