提高MongoDB上聚合查询的性能

时间:2018-08-18 13:50:46

标签: mongodb lambda

我对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秒钟以上才能完成。

有一些想法可以改善这一点?

2 个答案:

答案 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秒的时间内完成所有文档的处理。