使用datetime字段在MongoDB集合中高效地查找最近过滤的文档



我有一个很大的文档集合,其中包含日期时间字段,我需要为任何给定的查询列表检索最新的文档。

样本数据:

[
  {"_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游乐场供您参考。

最新更新