我对mongodb的聚合框架有很大的疑问。我将尽力解释这种情况,但是代码很清楚。
我们有一个收集类别和注释,每个注释都有一个类别ID字段和createdAt字段,我们希望按每个类别获取最后一个注释。
因此,我们制作下一个agreggate函数:
(async () =>{
//busco las categorias
const categoryCollection = db.collection('category');
const categoryList = await categoryCollection.find({},{ projection:{name: 1} }).toArray();
//genero un arrays de ids de categoria
const categoryIds = categoryList.map(function(e) {
return e._id;
});
//busco una nota por categoria ordenadas por fecha de creacion de forma descendente
const articlesColl = db.collection('note');
const articles = await articlesColl.aggregate([
{ $match: { "category":{$in: categoryIds }}},
{ $sort: { createdAt: -1 }},
{
$group: {
_id: "$category",
note: { $first: "$$ROOT"}
}
},
{ $replaceRoot: { newRoot: "$note" } },
{ $project : { _id : 1 ,title : 1, image : 1, category:1} },
{ $skip: skip},
{ $limit : limit }
],{allowDiskUse: true}).toArray();
callback(null, success(
//reemplazo los category id con el nombre
articles.map(
function(doc){
doc.categoryName = categoryList.find( e => e._id.equals(doc.category)).name;
return doc;
}
)
));
此查询按每个类别获取最后的注释,但此“吸”的性能。
我使用mongo地图集,并且警报向我显示了此信息:
查询无效率得分:258393,执行计数4,平均执行 时间2872 MS
这是查询的示例。
0:对象 $ match:对象 类别:物件 $ in:数组[23] 0:5a4536cd920f3a5acdf33a60 1:5a4536cd920f3a5acdf33a55 2:5a4536cd920f3a5acdf33a53 3:5a4536cd920f3a5acdf33a66 4:5a4536cd920f3a5acdf33a5a 5:5a4536cd920f3a5acdf33a56 6:5a4536cd920f3a5acdf33a51 7:5a4536cd920f3a5acdf33a58 8:5a4536cd920f3a5acdf33a5b 9:5a4536cd920f3a5acdf33a57 10:5a4536cd920f3a5acdf33a63 11:5a4536cd920f3a5acdf33a5d 12:5a4536cd920f3a5acdf33a5c 13:5a4536cd920f3a5acdf33a59 14:5a4536cd920f3a5acdf33a52 15:5a4536cd920f3a5acdf33a5e 16:5a4536cd920f3a5acdf33a65 17:5a4536cd920f3a5acdf33a61 18:5b202ef5d03337b3a0227daf 19:5a4536cd920f3a5acdf33a64 20:5a4536cd920f3a5acdf33a62 21:5a4536cd920f3a5acdf33a5f 22:5a4536cd920f3a5acdf33a54 1:对象 $ sort:对象 createdAt:-1 2:对象 $ group:对象 _id:$ category 注意:对象 $ first:$$ ROOT 3:对象 $ replaceRoot:对象 newRoot:$ note 4:对象 $ project:对象 _id:1 标题:1 图片:1 类别:1 5:对象 $ skip:0 6:对象 上限:8 2018年8月17日星期五上午10:11 6283毫秒 1033573 / 8nScanned / nReturned
这里最大的问题是此查询确实很慢,有时要花费6秒钟以上才能完成。
有一些想法可以改善这一点?
答案 0 :(得分:0)
请考虑您的集合大小,在内存中使用$sort
会浪费您太多的处理时间。
您应该为createAt
字段创建索引。
答案 1 :(得分:0)
查询效率低下意味着您返回的每个文档都会检查258393个文档。
您是否考虑过迭代categoryList并使用find来获取最新的笔记?
const articles = categoryList.map(function(e) {
return await articlesColl.Find(x => x.category == e._id).Sort({ createdAt: -1 }).Limit(1)
});
如果您在{category:1,createdAt:-1}上创建了索引,则运行该索引仅需要检查每个类别的单个文档(示例中共23个)。即使进行了额外的网络往返,将检查的文档数量减少100,000倍,也应该可以在不到6秒的时间内完成所有文档的处理。