我有一个很大的文档集合,其中包含日期时间字段,我需要为任何给定的查询列表检索最新的文档。
样本数据:
[
{"_id": "42.abc",
"ts_utc": "2019-05-27T23:43:16.963Z"},
{"_id": "42.def",
"ts_utc": "2019-05-27T23:43:17.055Z"},
{"_id": "69.abc",
"ts_utc": "2019-05-27T23:43:17.147Z"},
{"_id": "69.def",
"ts_utc": "2019-05-27T23:44:02.427Z"}
]
本质上,我需要获得";42〃;组的最新记录;69〃;组使用上面的样本数据;42〃;组将是文档";42.def";。
我目前的解决方案是一次查询每个组一个(使用PyMongo循环(,按ts_utc
字段排序,并将其限制为一个,但这真的很慢。
// Requires official MongoShell 3.6+
db = db.getSiblingDB("someDB");
db.getCollection("collectionName").find(
{
"_id" : /^42..*/
}
).sort(
{
"ts_utc" : -1.0
}
).limit(1);
有没有更快的方法来获得我想要的结果
假设您的所有文档都具有上面显示的格式,您可以将id分为两部分(使用点字符(,并使用聚合来查找每个第一个数组(数字(元素的最大元素。
这样你就可以一次性完成,而不是每一组都迭代。
db.foo.aggregate([
{ $project: { id_parts : { $split: ["$_id", "."] }, ts_utc : 1 }},
{ $group: {"_id" : { $arrayElemAt: [ "$id_parts", 0 ] }, max : {$max: "$ts_utc"}}}
])
正如@danh在评论中提到的,最好的方法可能是添加一个辅助字段来指示分组。您可以进一步索引辅助字段以提高性能。
这里有一种特殊的方法来导出字段并获得每个分组的最新结果:
db.collection.aggregate([
{
"$addFields": {
"group": {
"$arrayElemAt": [
{
"$split": [
"$_id",
"."
]
},
0
]
}
}
},
{
$sort: {
ts_utc: -1
}
},
{
"$group": {
"_id": "$group",
"doc": {
"$first": "$$ROOT"
}
}
},
{
"$replaceRoot": {
"newRoot": "$doc"
}
}
])
这是Mongo游乐场供您参考。