【问题标题】:How to speed up this aggregated query that only needs the latest 2 documents per category如何加快每个类别只需要最新 2 个文档的聚合查询
【发布时间】:2018-03-30 01:30:37
【问题描述】:

我有一个包含几百万个文档的集合,而且每天都会增长几千个。集合中的每个文档最多有 200 个属性。我想做的是创建一个查询,可以为我提供每个类别的最后 2 个文档。这是我已经完成的事情,但是速度很慢。

考虑以下结构:

db.createCollection('testing')
db.testing.createIndex({time:-1})
db.testing.createIndex({category:1})

使用以下示例文档:

db.testing.insert( { time: ISODate("2018-03-26T23:00:00.000Z"), category: 'a', 'value1':0 } )
db.testing.insert( { time: ISODate("2018-03-26T23:00:00.000Z"), category: 'b', 'value1':30 } )
db.testing.insert( { time: ISODate("2018-03-26T23:00:00.000Z"), category: 'c', 'value1':10 } )
db.testing.insert( { time: ISODate("2018-03-27T23:00:00.000Z"), category: 'a', 'value1':0 } )
db.testing.insert( { time: ISODate("2018-03-27T23:00:00.000Z"), category: 'b', 'value1':20 } )
db.testing.insert( { time: ISODate("2018-03-27T23:00:00.000Z"), category: 'c', 'value1':20 } )
db.testing.insert( { time: ISODate("2018-03-28T23:00:00.000Z"), category: 'a', 'value1':10 } )
db.testing.insert( { time: ISODate("2018-03-28T23:00:00.000Z"), category: 'b', 'value1':10 } )
db.testing.insert( { time: ISODate("2018-03-28T23:00:00.000Z"), category: 'c', 'value1':10 } )

我有以下疑问:

db.getCollection('testing').aggregate([
    { // Added a match hoping this would speed up the query because I know the last 2 documents are never older then 10 days
        '$match': {
            time:{'$lte':new Date(),'$gte':new Date(Date()-10)}
        }
    },
   { // Add sort because I want the most recent documents
        '$sort': {
            'time' : -1 
        }
    },
    { 
        '$group': {
            '_id': '$category',
            'docs': { '$push': '$$ROOT' },
        }
    },
    {
        '$project': {
            'top_two': { 
                '$slice': ['$docs', 2]
            }
        }
    }
], {allowDiskUse:true}) 

查询中的 $match 部分似乎只在分组之后执行,这使得在我的包含数百万个文档的大集合上一切都非常慢(执行时间分钟)。我确实从社区成员那里得到了加快查询速度的提示。他建议:“$group阶段的$push可以马上使用$slice,这样每个分类最多有2个item period。”

但是,我似乎无法使其正常工作或找到有关如何执行此操作的示例。但我绝对可以理解这在执行时间方面是多么有益。

加快查询速度的最佳方法是什么?

【问题讨论】:

  • category 字段的基数是多少?您是否期望拥有很多(即数千个)类别?
  • 另外,目前还没有在单个聚合阶段同时使用$push$slice 的方法。社区成员可以参考更新操作中的$push,这里可以有$slice修饰符。这在聚合管道中不可用。

标签: mongodb aggregation-framework grouping


【解决方案1】:

我刚刚比较了您使用和不使用$sort 阶段的查询结果。两者看起来一样:

因此,$sort 对您的输出的影响为零。这意味着如果我不指定$sort,它将使用您的time 索引将它们排列在输出中。只需删除$sort,这在您的情况下是不必要的。您的索引已经在为您排序结果。如何?因为您在time 字段上使用索引,并且您想根据time 进行排序(以相同的降序排列)。因此,即使您没有明确指定$sort,它也会按降序运行。希望你能理解!

阅读此处了解更多信息:Use indexes for sorting

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多