返回文章列表

文章

PostgreSQL中查询JSONBl类型的数据

目录
  1. 3️⃣ 存在性比较
  2. 4️⃣ 提取后再比较
  3. 5️⃣ 索引优化
  4. 这样 @>、? 这类查询会非常快。
在 **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);

这样 @>? 这类查询会非常快。#