【发布时间】: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