如何在MongoDB的$or查询中合并每个条件返回的首条记录
MongoDB实现多条件子查询各取首条并合并结果
错误原因
你原来的查询语法错误是因为**$limit是游标方法或聚合阶段操作符**,不能放在$or的筛选条件文档里,它不属于查询匹配条件的一部分。
正确解决方案
以下两种方法都能实现你要的需求:每个过滤条件取首条记录,最终合并所有结果。
方法一:使用$facet聚合(推荐,并行处理)
通过$facet并行处理多个子查询,每个子查询匹配条件、排序取最新记录、限制1条,最后合并结果:
db["mydata"].aggregate([ { $facet: { // 第一个子查询:device1+reader x+温度 temp_x: [ { $match: { "device": "device1", "reader": "x", "measurement": "temperature", "SourceTimeUtc": { "$lte": ISODate("2023-01-11T06:07:47.280Z") } }}, { $sort: { SourceTimeUtc: -1 } }, // 按时间倒序,确保取符合条件的最新记录 { $limit: 1 } ], // 第二个子查询:device1+reader y+温度 temp_y: [ { $match: { "device": "device1", "reader": "y", "measurement": "temperature", "SourceTimeUtc": { "$lte": ISODate("2023-01-11T06:07:47.280Z") } }}, { $sort: { SourceTimeUtc: -1 } }, { $limit: 1 } ], // 第三个子查询:device1+reader x+湿度 humidity_x: [ { $match: { "device": "device1", "reader": "x", "measurement": "humidity", "SourceTimeUtc": { "$lte": ISODate("2023-01-11T06:07:47.280Z") } }}, { $sort: { SourceTimeUtc: -1 } }, { $limit: 1 } ] } }, // 合并三个子查询的结果数组 { $project: { results: { $concatArrays: ["$temp_x", "$temp_y", "$humidity_x"] } }}, // 展开结果数组为单个文档 { $unwind: "$results" }, // 将每个结果文档作为根文档返回 { $replaceRoot: { newRoot: "$results" } } ])
方法二:使用$unionWith合并子查询
依次执行三个独立的子查询,每个子查询取首条记录,再通过$unionWith合并结果集:
db["mydata"].aggregate([ // 第一个子查询 { $match: { "device": "device1", "reader": "x", "measurement": "temperature", "SourceTimeUtc": { "$lte": ISODate("2023-01-11T06:07:47.280Z") } }}, { $sort: { SourceTimeUtc: -1 } }, { $limit: 1 }, // 合并第二个子查询结果 { $unionWith: { coll: "mydata", pipeline: [ { $match: { "device": "device1", "reader": "y", "measurement": "temperature", "SourceTimeUtc": { "$lte": ISODate("2023-01-11T06:07:47.280Z") } }}, { $sort: { SourceTimeUtc: -1 } }, { $limit: 1 } ] }}, // 合并第三个子查询结果 { $unionWith: { coll: "mydata", pipeline: [ { $match: { "device": "device1", "reader": "x", "measurement": "humidity", "SourceTimeUtc": { "$lte": ISODate("2023-01-11T06:07:47.280Z") } }}, { $sort: { SourceTimeUtc: -1 } }, { $limit: 1 } ] }} ])
注意事项
- 一定要添加
$sort: { SourceTimeUtc: -1 }:如果不指定排序,MongoDB返回的第一条记录是不确定的(依赖存储顺序),倒序排序能确保你拿到的是符合时间条件的最新记录。 - 如果你的需求是取最早的记录,把排序改为
{ SourceTimeUtc: 1 }即可。
内容的提问来源于stack exchange,提问作者Jennifer Zhao
相关产品推荐
相关产品推荐

