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