如何按不同国家字段查询MongoDB中对应最新日期的文档
解决方案
你可以通过一次MongoDB聚合查询完成需求,无需多次调用数据库,具体实现如下:
核心思路
利用聚合管道的$objectToArray操作符将动态的国家代码顶级字段转为可统一遍历的键值数组,再经过分组、过滤操作直接得到每个国家最新上报日期对应的所有文档title。
聚合查询语句
db.collection.aggregate([ // 1. 将文档中所有顶级字段转为{k: 字段名, v: 字段值}的数组,排除内置的_id、title字段 { $addFields: { countryData: { $filter: { input: { $objectToArray: "$$ROOT" }, cond: { $not: { $in: ["$$this.k", ["_id", "title"]] } } } } } }, // 2. 将countryData数组拆分为单条记录,每个国家对应一条 { $unwind: "$countryData" }, // 3. 过滤掉data为null、无lastReportDate的无效条目 { $match: { "countryData.v.data": { $ne: null }, "countryData.v.data.lastReportDate": { $exists: true } } }, // 4. 按国家代码分组,计算每个国家的最大上报日期,同时保存该国家所有的日期+title映射 { $group: { _id: "$countryData.k", maxDate: { $max: "$countryData.v.data.lastReportDate" }, allEntries: { $push: { date: "$countryData.v.data.lastReportDate", title: "$title" } } } }, // 5. 过滤出每个国家下日期等于最大日期的所有title { $project: { _id: 0, country: "$_id", latestTitles: { $map: { input: { $filter: { input: "$allEntries", cond: { $eq: ["$$this.date", "$maxDate"] } } }, in: "$$this.title" } }, latestReportDate: "$maxDate" } } ])
查询结果示例
针对你给出的示例数据,执行上述查询后将得到如下结果:
[ { "country": "US", "latestTitles": ["1"], "latestReportDate": "2021-09-09" }, { "country": "GB", "latestTitles": ["4"], "latestReportDate": "2021-09-08" }, { "country": "NZ", "latestTitles": ["5"], "latestReportDate": "2021-09-06" } ]
方案说明
- 全程仅需1次数据库查询,没有额外的IO开销,满足你减少查询次数的要求
- 自动适配所有国家代码字段,无需提前枚举国家列表,即使单文档包含180个国家字段也可正常处理
- 如果不需要保留最新日期字段,可在
$project阶段删除对应配置
内容的提问来源于stack exchange,提问作者Yash
相关产品推荐
相关产品推荐

