PostgreSQL JSON 操作符与 jsonb 高级操作

PostgreSQL 对 JSON 的支持不仅限于存储数据。实际开发中,jsonb 更常用,因为它会以二进制格式存储 JSON,并提供结构化查询、修改和索引能力。
对于字段结构存在一定变化、但又希望直接利用数据库查询能力的业务数据,jsonb 是比较合适的方案。

常用操作符

PostgreSQL 提供了一组专门用于 JSON 和 JSONB 的操作符,可以完成字段提取、路径访问、结构匹配和键存在判断。

操作符 作用 示例
-> 获取 JSON 对象或数组元素,结果仍为 JSON data->'user'
->> 获取元素并转换为文本 data->'user'->>'name'
#> 按路径获取 JSON data#>'{user,address}'
#>> 按路径获取文本 data#>>'{user,address,city}'
@> 判断左侧是否包含右侧 JSON 结构 data @> '{"status":"paid"}'
<@ 判断左侧是否被右侧 JSON 包含 data <@ '{"status":"paid"}'
? 判断对象是否存在指定键 data ? 'status'
? | 判断是否存在任意一个指定键 data ? | array['status','type']
?& 判断是否同时存在全部指定键 data ?& array['status','type']

其中,->->> 是最常用的一组操作符:前者适合继续进行 JSON 操作,后者适合与普通字符串进行比较。@> 则是 JSONB 查询中非常重要的操作,适合判断对象是否包含指定字段和值。

JSONB 修改与拆分

PostgreSQL 可以直接修改 JSONB,而不需要先取出 JSON、在应用层修改后再完整写回。jsonb_set() 可以更新指定路径,- 可以删除顶层字段,#- 可以删除嵌套路径。例如可以使用 jsonb_set(data, '{user,name}', '"Tom"') 修改用户名称。

对于数组和对象,还可以使用 jsonb_array_elements()jsonb_each() 等函数将 JSONB 拆分成多行,从而参与 JOIN、聚合和统计分析。这对于处理第三方接口数据、动态属性以及配置类数据尤其有用。

需要注意的是,JSONB 更新并不是简单的原地修改。大型 JSON 文档频繁更新时可能产生较明显的写放大,因此不适合把大量高频变化字段集中在一个 JSONB 文档中。

GIN 索引

如果业务大量使用 @>? 等 JSONB 查询,可以建立 GIN 索引:

CREATE INDEX idx_data ON orders USING GIN (data);

GIN 默认使用 jsonb_ops,支持的操作范围较广;jsonb_path_ops 更适合以 @> 为主的包含查询,索引通常更紧凑,但支持的操作范围较小。因此索引选择应该根据实际查询模式决定,而不是看到 JSONB 就直接建立 GIN。

JSONB 的核心价值,是在关系型数据库中兼顾结构化查询能力与半结构化数据的灵活性。稳定且高频查询、排序或关联的字段,仍然应该设计为普通列;JSONB 更适合承载结构灵活、扩展性较强的数据。

如果你有魔法,你可以看到一个评论框~