我知道这个问题以前是在SO处提出的-但我似乎找不到如何处理较大集合中的聚合分组的方法。我有一套+1000万条记录,但实在无济于事。
运行MongoDB v 3.2。
模式中具有字段__createDateUtc
(ISODate),我正在尝试以下管道:
db.transactions.aggregate([
{
$project: {
__createDateUtc: 1
}
},
{
$group: {
'_id': { $year: '$__createDateUtc' },
'count': {$sum: 1},
}
},
{
$limit: 10
},
])
运行时间为+20秒。可以更快吗?这是一个非常简单的管道-的确如此-在这种情况下是否还有其他策略可能会有所帮助?
答案 0 :(得分:0)
我用四种不同的方式进行基准测试,以获得所需的结果。结果令人沮丧。
再次,其架构类似于:
{
"_id" : ObjectId("5d665491fd5852755236a5dc"),
...
"__createDateUtc" : ISODate("2019-08-28T10:16:49Z"),
"__createDate" : {
"year" : 2019,
"month" : 8,
"day" : 28,
"yearMonth" : 201908,
"yearMonthDay" : 20190829
}
}
结果:
// Group by __createDate.yearMonth
db.transactions.aggregate([
{ $group: {
'_id': '$__createDate.yearMonth',
'count': {$sum: 1},
} },
{ $limit: 10 },
{ $sort: {'_id': -1 } }
])
// 20 169 ms
// Group by year and month
db.transactions.aggregate([
{$group: {
'_id': {year: '$__createDate.year', month: '$__createDate.month' },
'count': {$sum: 1},
}},
{ $limit: 10 },
{ $sort: {'_id': -1 } }
])
// 23 777 ms
// Group by calculating year and month from ISODate
db.transactions.aggregate([
{$group: {
'_id': {year: { $year: '$__createDateUtc' }, month: { $month: '$__createDateUtc' } },
'count': {$sum: 1},
}},
{ $limit: 10 },
{ $sort: {'_id': -1 } }
])
// 16 444 ms
// Last stupid method to just run many queries with count
var years = [2017, 2018, 2019];
var results = {}
years.forEach(year => {
results[year] = {};
for(var i = 1; i < 13; i++) {
var count = db.transactions.find({'__createDate.year': year, '__createDate.month': i}).count();
if(count > 0) results[year][i] = count;
}
})
// 10 701 ms
如您所见,仅运行多个计数的最后一种方法是最快的。特别是因为与其他三种方法相比,我实际上要获取更多的数据。
这对我来说似乎很愚蠢。我知道MongoDB不是搜索引擎,但是仍然。聚合根本不是很快。让我想将数据同步到弹性搜索,并尝试在ES中进行汇总。