文章
PostgreSQL中查询JSONBl类型的数据
在 **PostgreSQL** 里,`jsonb` 类型和普通标量字段不同,比较需要用 **专门的运算符**。我帮你分几类梳理:
---
## 1️⃣ 基础比较:相等 / 不等
```sql
-- 完全相等(结构和值必须一样,key顺序不影响)
SELECT * FROM video_info WHERE language = '"韩语"'::jsonb;
这样
-- 不等 SELECT * FROM video_info WHERE language <> '"英语"'::jsonb;
📌 注意:字符串必须写成 JSON 格式 → `'"值"'::jsonb`。
---
## 2️⃣ 包含/被包含
- **@\>**:左边是否包含右边
- **\<@**:左边是否被右边包含
```sql
-- 查询 language 字段包含 "韩语"
SELECT * FROM video_info
WHERE language @> '["韩语"]'::jsonb;
-- 查询 genres 精确包含 { "类型": "剧情" }
SELECT * FROM video_info
WHERE genres @> '{"类型": "剧情"}'::jsonb;
3️⃣ 存在性比较#
- ?:key 或 value 是否存在
- ?|:是否存在任意一个
- ?&:是否存在所有
-- 查询 language 数组里是否有 "韩语"
SELECT * FROM video_info WHERE language ? '韩语';
-- 查询 genres 是否有 "剧情" 或 "喜剧"
SELECT * FROM video_info WHERE genres ?| array['剧情','喜剧'];
-- 查询 genres 必须同时有 "剧情" 和 "爱情"
SELECT * FROM video_info WHERE genres ?& array['剧情','爱情'];
4️⃣ 提取后再比较#
有时候你需要把 jsonb 里的值提取出来,再和普通类型比较:
-- 提取 release_year 作为文本,再比较
SELECT * FROM video_info
WHERE release_year::text = '"2025"';
-- 提取 duration 数组第一个值,转 int 再比较
SELECT * FROM video_info
WHERE (duration->>0)::int > 100;
5️⃣ 索引优化#
如果经常查 jsonb,最好建 GIN 索引:
CREATE INDEX idx_video_language ON video_info USING gin (language jsonb_path_ops);