Postgre Jsonb vs Mongo Pipeline

1. 基础 CRUD

操作 PostgreSQL JSONB MongoDB Pipeline
新增 INSERT INTO public.cfx_mongo (id, cfx_message, create_time) VALUES ('5', '{"MessageName":"CFX.TEST"}', NOW()); db.cfx_mongo.insertOne({ _id: "5", cfx_message: { MessageName: "CFX.TEST" }, create_time: new Date() })
修改 UPDATE public.cfx_mongo SET cfx_message = '{"MessageName":"CFX.AAAA.DE00000000"}' WHERE id = '5'; db.cfx_mongo.updateOne({ _id: "5" }, { $set: { "cfx_message.MessageName": "CFX.AAAA.DE00000000" } })
删除 DELETE FROM public.cfx_mongo WHERE id = '5'; db.cfx_mongo.deleteOne({ _id: "5" })
查询全部 SELECT id, cfx_message, create_time FROM public.cfx_mongo ORDER BY id; db.cfx_mongo.find({}, { _id: 1, cfx_message: 1, create_time: 1 }).sort({ _id: 1 })

2. 条件查询

操作 PostgreSQL JSONB MongoDB Pipeline
等值查询 (=) SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message->>'Source' = 'CFX.A00.OT05460002'; db.cfx_mongo.find({ "cfx_message.Source": "CFX.A00.OT05460002" }, { _id: 1, cfx_message: 1, create_time: 1 })
不等值查询 (!=) SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message->>'Source' != 'CFX.A00.OT05460002'; db.cfx_mongo.find({ "cfx_message.Source": { $ne: "CFX.A00.OT05460002" } }, { _id: 1, cfx_message: 1, create_time: 1 })

3. 嵌套查询

操作 PostgreSQL JSONB MongoDB Pipeline
单层嵌套 SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message -> 'MessageBody' ->> '$type' = 'CFX.Plus.InformationSystem.UnitValidation.ValidateUpdateUnitsRequest, CFX.Structures.GenericEquipment'; db.cfx_mongo.find({ "cfx_message.MessageBody.$type": "CFX.Plus.InformationSystem.UnitValidation.ValidateUpdateUnitsRequest, CFX.Structures.GenericEquipment" }, { _id: 1, cfx_message: 1, create_time: 1 })
深度嵌套 (->) SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message -> 'MessageBody' -> 'PrimaryResult' ->> 'Result' = 'Passed'; db.cfx_mongo.find({ "cfx_message.MessageBody.PrimaryResult.Result": "Passed" }, { _id: 1, cfx_message: 1, create_time: 1 })
深度嵌套 (#>>) SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message #>> '{MessageBody,PrimaryResult,Result}' = 'Passed'; db.cfx_mongo.find({ "cfx_message.MessageBody.PrimaryResult.Result": "Passed" }, { _id: 1, cfx_message: 1, create_time: 1 })

4. 组合条件查询

操作 PostgreSQL JSONB MongoDB Pipeline
AND 条件 SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message -> 'MessageBody' ->> '$type' = 'CFX.Plus.InformationSystem.UnitValidation.ValidateUpdateUnitsRequest, CFX.Structures.GenericEquipment' AND cfx_message -> 'MessageBody' -> 'PrimaryResult' ->> 'Result' = 'Passed'; db.cfx_mongo.find({ $and: [ { "cfx_message.MessageBody.$type": "CFX.Plus.InformationSystem.UnitValidation.ValidateUpdateUnitsRequest, CFX.Structures.GenericEquipment" }, { "cfx_message.MessageBody.PrimaryResult.Result": "Passed" } ] }, { _id: 1, cfx_message: 1, create_time: 1 })
OR 条件 SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message -> 'MessageBody' ->> '$type' = 'CFX.Plus.InformationSystem.UnitValidation.ValidateUpdateUnitsRequest, CFX.Structures.GenericEquipment' OR cfx_message -> 'MessageBody' -> 'PrimaryResult' ->> 'Result' = 'Passed'; db.cfx_mongo.find({ $or: [ { "cfx_message.MessageBody.$type": "CFX.Plus.InformationSystem.UnitValidation.ValidateUpdateUnitsRequest, CFX.Structures.GenericEquipment" }, { "cfx_message.MessageBody.PrimaryResult.Result": "Passed" } ] }, { _id: 1, cfx_message: 1, create_time: 1 })

5. 键存在性查询

操作 PostgreSQL JSONB MongoDB Pipeline
包含指定键 (?) SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message ? 'factory'; db.cfx_mongo.find({ "cfx_message.factory": { $exists: true } }, { _id: 1, cfx_message: 1, create_time: 1 })
包含任意一个指定键 (`? `) `SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message ?
包含所有指定键 (?&) SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message ?& ARRAY['factory', 'MessageBody']; db.cfx_mongo.find({ $and: [ { "cfx_message.factory": { $exists: true } }, { "cfx_message.MessageBody": { $exists: true } } ] }, { _id: 1, cfx_message: 1, create_time: 1 })

6. 包含查询 (@>)

操作 PostgreSQL JSONB MongoDB Pipeline
包含指定键值对 SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message @> '{"factory": "DET7"}'; db.cfx_mongo.find({ "cfx_message.factory": "DET7" }, { _id: 1, cfx_message: 1, create_time: 1 })
同时满足多个条件 SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message @> '{"factory": "DET7", "testData": ""}'; db.cfx_mongo.find({ "cfx_message.factory": "DET7", "cfx_message.testData": "" }, { _id: 1, cfx_message: 1, create_time: 1 })

7. 路径查询(#>> / #>-> / ->> 的区别)

操作 PostgreSQL JSONB MongoDB Pipeline
-> + ->> 逐级访问 SELECT cfx_message -> 'MessageBody' ->> '$type' FROM public.cfx_mongo; db.cfx_mongo.find({}, { "cfx_message.MessageBody.$type": 1 })
#>> 路径访问(返回文本) SELECT cfx_message #>> '{MessageBody,PrimaryResult,Result}' FROM public.cfx_mongo; db.cfx_mongo.find({}, { "cfx_message.MessageBody.PrimaryResult.Result": 1 })
#> 路径访问(返回 JSON) SELECT cfx_message #> '{MessageBody,PrimaryResult}' FROM public.cfx_mongo; db.cfx_mongo.find({}, { "cfx_message.MessageBody.PrimaryResult": 1 })

路径访问语法对比:

PostgreSQL 说明 MongoDB
cfx_message -> 'MessageBody' ->> '$type' 逐级访问,适合层级少 cfx_message.MessageBody.$type
cfx_message #>> '{MessageBody,$type}' 路径访问,适合层级深 cfx_message.MessageBody.$type
cfx_message #>> ARRAY['MessageBody', '$type'] 数组形式路径 cfx_message.MessageBody.$type

8. 范围查询

操作 PostgreSQL JSONB MongoDB Pipeline
等于 SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE (cfx_message #>> '{MessageBody,PrimaryResult,PositionNumber}')::INT = 0; db.cfx_mongo.find({ "cfx_message.MessageBody.PrimaryResult.PositionNumber": 0 }, { _id: 1, cfx_message: 1, create_time: 1 })
大于 SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE (cfx_message #>> '{MessageBody,PrimaryResult,PositionNumber}')::INT > 0; db.cfx_mongo.find({ "cfx_message.MessageBody.PrimaryResult.PositionNumber": { $gt: 0 } }, { _id: 1, cfx_message: 1, create_time: 1 })
BETWEEN SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE (cfx_message #>> '{MessageBody,PrimaryResult,PositionNumber}')::INT BETWEEN 0 AND 100; db.cfx_mongo.find({ "cfx_message.MessageBody.PrimaryResult.PositionNumber": { $gte: 0, $lte: 100 } }, { _id: 1, cfx_message: 1, create_time: 1 })
日期范围 SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE (cfx_message #>> '{TimeStamp}') BETWEEN '2025-08-19T11:53:12.1791536+08:00' AND '2025-08-19T11:53:12.1791536+08:00'; db.cfx_mongo.find({ "cfx_message.TimeStamp": { $gte: ISODate("2025-08-19T11:53:12.1791536+08:00"), $lte: ISODate("2025-08-19T11:53:12.1791536+08:00") } }, { _id: 1, cfx_message: 1, create_time: 1 })

9. 模糊查询

操作 PostgreSQL JSONB MongoDB Pipeline
LIKE(顶层字段) SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message ->> 'MessageName' LIKE '%ValidateUpdateUnitsRequest%'; db.cfx_mongo.find({ "cfx_message.MessageName": { $regex: "ValidateUpdateUnitsRequest" } }, { _id: 1, cfx_message: 1, create_time: 1 })
LIKE(嵌套字段) SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message -> 'MessageBody' ->> '$type' LIKE '%ValidateUpdateUnitsRequest%'; db.cfx_mongo.find({ "cfx_message.MessageBody.$type": { $regex: "ValidateUpdateUnitsRequest" } }, { _id: 1, cfx_message: 1, create_time: 1 })
LIKE(深层路径) SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message #>> '{MessageBody,$type}' LIKE '%ValidateUpdateUnitsRequest%'; db.cfx_mongo.find({ "cfx_message.MessageBody.$type": { $regex: "ValidateUpdateUnitsRequest" } }, { _id: 1, cfx_message: 1, create_time: 1 })
ILIKE(忽略大小写) SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message #>> '{MessageBody,$type}' ILIKE '%validateupdateunitsrequest%'; db.cfx_mongo.find({ "cfx_message.MessageBody.$type": { $regex: "validateupdateunitsrequest", $options: "i" } }, { _id: 1, cfx_message: 1, create_time: 1 })
正则匹配 SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message #>> '{MessageBody,$type}' ~ '.*ValidateUpdateUnitsRequest.*'; db.cfx_mongo.find({ "cfx_message.MessageBody.$type": { $regex: ".*ValidateUpdateUnitsRequest.*" } }, { _id: 1, cfx_message: 1, create_time: 1 })

10. 索引创建

目的 PostgreSQL JSONB MongoDB
GIN 全文索引 CREATE INDEX idx_cfx_message_gin ON public.cfx_mongo USING GIN (cfx_message); db.cfx_mongo.createIndex({ "cfx_message": "text" })
顶层字段索引 CREATE INDEX idx_cfx_message_name ON public.cfx_mongo ((cfx_message ->> 'MessageName')); db.cfx_mongo.createIndex({ "cfx_message.MessageName": 1 })
嵌套字段索引 CREATE INDEX idx_cfx_message_body_primary_result ON public.cfx_mongo ((cfx_message #>> '{MessageBody,PrimaryResult,Result}')); db.cfx_mongo.createIndex({ "cfx_message.MessageBody.PrimaryResult.Result": 1 })
组合索引 CREATE INDEX idx_cfx_message_unique ON public.cfx_mongo ((cfx_message ->> 'MessageName'), (cfx_message ->> 'UniqueID')); db.cfx_mongo.createIndex({ "cfx_message.MessageName": 1, "cfx_message.UniqueID": 1 })

11. 聚合查询

操作 PostgreSQL JSONB MongoDB Pipeline
数组查询 SELECT id, cfx_message, create_time FROM public.cfx_mongo WHERE cfx_message -> 'tags' @> '["urgent"]'; db.cfx_mongo.find({ "cfx_message.tags": "urgent" }, { _id: 1, cfx_message: 1, create_time: 1 })
分组统计 SELECT cfx_message ->> 'MessageName' AS message_name, COUNT(*) AS count FROM public.cfx_mongo GROUP BY cfx_message ->> 'MessageName'; db.cfx_mongo.aggregate([ { $group: { _id: "$cfx_message.MessageName", count: { $sum: 1 } } } ])

12. 总结对比

维度 PostgreSQL JSONB MongoDB
查询语法 SQL + JSONB 操作符 类 JSON 的查询语法
学习曲线 需要理解 JSONB 操作符 直观,易上手
索引灵活性 高(多种索引类型)
事务支持 完整 ACID 多文档事务(较新版本)
嵌套查询 使用 ->->>#>> 使用点号路径
正则查询 LIKE~ 操作符 $regex 操作符
数组查询 @> 包含操作符 直接查询数组元素
聚合能力 标准 SQL GROUP BY 聚合管道
数据完整性 强(约束、触发器、外键) 弱(应用层保证)
更新方式 整行更新(MVCC) 字段级更新

13. 迁移注意事项

  1. 查询语法转换 :MongoDB 点号路径 → PostgreSQL 的 ->>#>> 操作符
  2. 索引策略:根据实际查询模式选择 GIN 或 B-tree 表达式索引
  3. 性能验证 :使用 EXPLAIN ANALYZE 验证索引是否生效
  4. 数据完整性:利用 PostgreSQL 约束保证数据质量
  5. NULL 值处理:JSONB 中不存在的字段返回 NULL,与 MongoDB 的 undefined 处理逻辑不同
  6. 事务支持:PostgreSQL 提供完整 ACID 事务