当前位置: 首页 > news >正文

PostgreSQL JSONB 操作符详解

概述

PostgreSQL 提供了专门的 JSONB 类型和操作符,用于高效存储和查询 JSON 数据。JSONB 以二进制格式存储,支持索引和快速字段访问。


核心操作符

1.->操作符

作用:提取 JSON 字段,返回JSON 类型

语法:

jsonb_column->'key'

示例:

-- payload: {"name": "张三", "age": 25}SELECTpayload->'name'FROMusers;-- 结果: "张三" (JSON 字符串,带引号)SELECTpayload->'age'FROMusers;-- 结果: 25 (JSON 数字)

特点:

  • 返回 JSON 类型(保留引号、数据类型)
  • 适合继续链式操作

2.->>操作符

作用:提取 JSON 字段,返回TEXT 类型

语法:

jsonb_column->>'key'

示例:

-- payload: {"name": "张三", "age": 25}SELECTpayload->>'name'FROMusers;-- 结果: 张三 (纯文本,无引号)SELECTpayload->>'age'FROMusers;-- 结果: "25" (文本字符串)

特点:

  • 返回 TEXT 类型(去除引号)
  • 适合直接显示或字符串比较

3.#>操作符

作用:提取嵌套路径,返回JSON 类型

语法:

jsonb_column#> '{key1,key2,key3}'

示例:

-- payload: {"user": {"address": {"city": "北京"}}}SELECTpayload#>'{user,address,city}' FROM users;-- 结果: "北京" (JSON 字符串)

特点:

  • 支持多层嵌套访问
  • 返回 JSON 类型

4.#>>操作符

作用:提取嵌套路径,返回TEXT 类型

语法:

jsonb_column#>> '{key1,key2,key3}'

示例:

-- payload: {"user": {"address": {"city": "北京"}}}SELECTpayload#>>'{user,address,city}' FROM users;-- 结果: 北京 (纯文本)

特点:

  • 支持多层嵌套访问
  • 返回 TEXT 类型

对比总结

操作符返回类型用途示例
->JSON单层提取,保持 JSON 格式payload->'name'
->>TEXT单层提取,转为文本payload->>'name'
#>JSON多层嵌套提取,保持 JSON 格式payload#>'{a,b,c}'
#>>TEXT多层嵌套提取,转为文本payload#>>'{a,b,c}'

实际应用示例

场景 1:直接查询字段

-- 表结构CREATETABLEpartner_level_lock_push_log(id BIGSERIALPRIMARYKEY,payload JSONBNOTNULL,push_statusSMALLINTDEFAULT0);-- 查询特定字段SELECTid,payload->>'fiscalYear'asfiscal_year,payload->>'fiscalQuarter'asfiscal_quarter,payload->>'incentiveId'asincentive_idFROMpartner_level_lock_push_logWHEREpush_statusIN(0,-1);

场景 2:条件过滤

-- 根据 JSON 字段过滤SELECT*FROMpartner_level_lock_push_logWHEREpayload->>'status'='locked';-- 数值比较SELECT*FROMpartner_level_lock_push_logWHERE(payload->>'age')::int>25;

场景 3:批量提取并映射到对象

<!-- MyBatis XML --><selectid="selectPendingLogs"resultType="java.lang.String">SELECT payload FROM ${tableName} WHERE push_status IN (0, -1) ORDER BY id ASC LIMIT #{limit}</select>
// Java 代码List<String>payloadList=mapper.selectPendingLogs(tableName,1000);List<AnaplanPartnerLevelLockDo>dataList=newArrayList<>();for(Stringpayload:payloadList){AnaplanPartnerLevelLockDolockDo=JSON.parseObject(payload,AnaplanPartnerLevelLockDo.class);dataList.add(lockDo);}tip:也可以不用转换,直接从数据库返回json object ,后续使用object

性能优化建议

✅ 推荐做法

  1. 直接查询 payload 字段

    SELECTpayloadFROMtableWHERE...

    然后在 Java 中一次性反序列化。

  2. 使用 GIN 索引加速查询

    CREATEINDEXidx_payload_ginONtableUSINGGIN(payload);
  3. 针对常用字段创建表达式索引

    CREATEINDEXidx_fiscal_yearONtable((payload->>'fiscalYear'));

❌ 避免的做法

  1. 不要在 SQL 中逐个字段提取

    -- 低效:数据库要做多次 JSON 解析SELECTpayload->>'field1',payload->>'field2',payload->>'field3',...FROMtable;
  2. 不要混合使用 JSON 和关系型字段

    • 如果某个字段需要频繁查询/排序,应该单独建列
    • JSONB 适合存储结构化但不常查询的数据

常见错误

错误 1:混淆->->>

-- 错误:返回 JSON 类型,无法直接比较SELECT*FROMtableWHEREpayload->'status'='active';-- 正确:返回 TEXT 类型SELECT*FROMtableWHEREpayload->>'status'='active';

错误 2:嵌套路径格式错误

-- 错误:缺少花括号SELECTpayload#>'user,address,city' FROM table;-- 正确:需要花括号SELECTpayload#>'{user,address,city}' FROM table;

错误 3:类型转换问题

-- 错误:文本比较SELECT*FROMtableWHEREpayload->>'age'>25;-- 正确:显式转换SELECT*FROMtableWHERE(payload->>'age')::int>25;

最佳实践

1. 简单场景:直接查 payload

-- 最简单最高效SELECTpayloadFROMtableWHEREpush_status=0;

Java 端反序列化一次即可。

2. 部分字段提取:只取需要的字段

SELECTpayload->>'fiscalYear'asfiscal_year,payload->>'incentiveId'asincentive_idFROMtableWHEREpush_status=0;

适用于只需要少数字段的场景。

3. 复杂查询:结合索引

-- 创建索引CREATEINDEXidx_statusONtable((payload->>'status'));-- 利用索引查询SELECTpayloadFROMtableWHEREpayload->>'status'='locked';

总结

  • ->/->>: 单层提取
  • #>/#>>: 多层嵌套提取
  • 箭头单数 (->,#>): 返回 JSON 类型
  • 箭头双数 (->>,#>>): 返回 TEXT 类型
  • 最佳实践: 直接查询payload字段,在应用层反序列化
http://www.jsqmd.com/news/1150614/

相关文章:

  • 如何快速获取网盘直链:开源下载助手的终极指南
  • UNet 跳跃连接 Concatenate vs Add:3种融合方式代码对比与显存开销分析
  • 如何快速掌握几何光学仿真?Ray Optics Simulation终极入门指南
  • Bilibili-Old终极指南:3分钟找回经典B站界面的完整方案
  • Kubernetes二进制部署实战:v1.35.0高可用集群从零构建
  • 昇腾CANN 6.0.1 算子开发实战:TBE DSL vs TIK vs AICPU 3种方式性能对比
  • K-S检验法实战:3步验证数据是否符合泊松/均匀/指数分布
  • MindSpore Serving 1.5 部署实战:5 分钟搭建 ResNet-50 模型 gRPC/RESTful 推理服务
  • LibTV本地部署指南:AI视频生成从环境配置到生产实践
  • VGG-16 迁移学习实战:乳腺超声图像3分类,Kaggle数据集准确率超92%
  • Deep Mutual Learning 与知识蒸馏对比:CIFAR-100/ImageNet 3 组实验解析性能差异
  • AutoUU API 逆向工程解析:4个核心接口实现饰品租赁自动化上架
  • 柯桥水司落地“脉信AI语音智能体+AI客服智能体”,实现私有化、信创化部署
  • A股年报词频分析:从7个关键词到构建行业趋势词库的3步方法
  • 弹簧振子周期公式 3 种验证方法对比:PASCO实测、Python模拟与理论误差分析
  • 如何快速完成学术论文排版:厦门大学LaTeX模板完整指南
  • Hunyuan3D-2源码级实战:3D生成模型的调试、优化与工业落地
  • 【爱马仕】Hermes Agent 本地智能体 Windows 搭建配置流程(含安装包)
  • 免费在线法线贴图生成器:3分钟将普通图片变3D纹理
  • Python 3.12 + Pandas 复现 MathorCup B题:共享单车时空分布与OD矩阵计算
  • 15分钟极速上手:开源卫星图像大气校正工具ACOLITE终极指南
  • JPEG 压缩原理深度解析:10:1 到 40:1 压缩比下,图片大小差异的量化分析
  • 决策树算法实战:ID3/C4.5/CART 3大经典算法对比与Python实现
  • 免费在线光学仿真工具终极指南:5分钟创建专业2D光学系统
  • 深度剖析RevokeMsgPatcher:Windows平台即时通讯防撤回的二进制修改技术解析
  • Seurat 4.3.0 单细胞数据预处理实战:4步封装函数实现乳腺癌数据质控与聚类
  • 洛雪音乐桌面版:免费开源跨平台音乐聚合播放器终极指南
  • ID3决策树Python实现:从信息熵到分类预测的5个核心函数解析
  • 随机森林回归特征重要性:5种评估方法对比与 Python 3.11 实战解读
  • 如何安全使用哔哩下载姬:B站视频离线观看的终极指南