MongoDB中高效查询捆绑数据内指定对象的最新时间记录
MongoDB 高效查询指定人员在区域的最后出现时间
示例集合数据
[ { "_id": "", "at": ISODate("2022-11-19T10:00:00Z"), "areaId": 3, "data": [ { "name": "a", "sec": 34, "x": 10.3, "y": 23.3 }, { "name": "a", "sec": 36, "x": 10.3, "y": 23.3 }, { "name": "b", "sec": 37, "x": 10.3, "y": 23.3 } ] }, { "_id": "", "at": ISODate("2022-11-19T10:01:00Z"), "areaId": 3, "data": [ { "name": "a", "sec": 10, "x": 10.3, "y": 23.3 }, { "name": "b", "sec": 12, "x": 10.3, "y": 23.3 } ] } ]
需求说明
集合以分钟为单位打包存储人员的秒级位置数据,需以最优性能查询指定姓名的人员在指定区域的最后出现时间(精确到秒)。
解决方案
1. 创建最优复合索引
先创建针对性的复合索引,避免全表扫描,大幅提升查询性能:
db.your_collection_name.createIndex({ areaId: 1, at: -1, "data.name": 1 })
索引逻辑:
areaId: 1:等值过滤指定区域,快速缩小文档范围at: -1:按分钟时间倒序排序,优先定位最新的分钟数据包"data.name": 1:提前过滤包含目标姓名的文档,减少后续处理量
2. 执行查询语句
使用聚合管道实现精确查询,步骤清晰且高效:
db.your_collection_name.aggregate([ // 过滤指定区域且包含目标姓名的文档 { $match: { areaId: 3, "data.name": "a" } }, // 按分钟时间倒序,优先处理最新的数据包 { $sort: { at: -1 } }, // 展开data数组,便于单独处理每条人员记录 { $unwind: "$data" }, // 只保留目标姓名的记录 { $match: { "data.name": "a" } }, // 计算完整的出现时间(分钟时间+秒数偏移) { $addFields: { lastSeenTime: { $dateAdd: { startDate: "$at", unit: "second", amount: "$data.sec" } } } }, // 按完整时间倒序,取最新的一条记录 { $sort: { lastSeenTime: -1 } }, { $limit: 1 }, // 投影返回格式化后的结果字段 { $project: { _id: 0, 姓名: "$data.name", 区域ID: "$areaId", 最后出现时间: { $dateToString: { format: "%Y-%m-%d %H:%M:%S", date: "$lastSeenTime" } } } } ])
查询结果示例
{ "姓名" : "a", "区域ID" : 3, "最后出现时间" : "2022-11-19 10:01:10" }
性能说明
- 索引命中:
$match和$sort阶段完全利用复合索引,避免内存排序和全表扫描 - 数据裁剪:提前过滤无关文档和记录,减少后续聚合阶段的数据处理量
- 终止逻辑:
$limit:1在找到第一条最新记录后立即终止查询,无需处理全部数据
内容的提问来源于stack exchange,提问作者Mehmet Serkan Ekinci
相关产品推荐
相关产品推荐

