提高mongo查询性能

时间:2017-06-06 18:55:27

标签: node.js mongodb keystonejs

我正在使用一个名为Keystone的基于节点的CMS系统,它使用MongoDB作为数据存储,对数据和访问提供相当自由的控制。我有一个非常复杂的模型叫做 Family ,它有大约250个字段,一堆关系和十几种方法。我的网站上有一个表单,允许用户输入所需的信息来创建新的系列记录,但是处理时间很长(本地主机为12秒,Heroku实例为30秒) 。我遇到的问题是Heroku为任何运行超过30秒的进程发出应用程序错误,这意味着我需要优化我的查询。除一个功能外,所有处理都很快发生。以下是有问题的功能:

const Family = keystone.list( 'Family' );

exports.getNextRegistrationNumber = ( req, res, done ) => {

    console.time('get registration number');

    const locals = res.locals;

    Family.model.find()
        .select( 'registrationNumber' )
        .exec()
        .then( families => {

            // get an array of registration numbers
            const registrationNumbers = families.map( family => family.get( 'registrationNumber' ) );

            // get the largest registration number
            locals.newRegistrationNumber = Math.max( ...registrationNumbers ) + 1;

            console.timeEnd('get registration number');

            done();

        }, err => {

            console.timeEnd('get registration number');

            console.log( 'error setting registration number' );

            console.log( err );

            done();
        });

};

我的.then()中的处理以毫秒为单位发生,但Family.model.find()执行的时间太长。任何关于如何加快速度的建议将不胜感激。查询正在尝试挖掘大约40,000个族记录,并且registrationNumber字段上已有索引。

1 个答案:

答案 0 :(得分:4)

then()快速执行但find()需要一段时间才有意义;在一组记录中找到最大值是一个相对快速的数据库操作,而获取该集合可能非常耗时,具体取决于许多因素。

如果您只是通过REST或某种可视界面阅读数据并将其呈现给用户,您可以使用lean()来返回普通的javascript对象。默认情况下,您返回一个mongoose.Document,在您的情况下是不必要的,因为在您的读取查询后似乎没有任何数据操作;你刚收到数据。

更重要的是,您似乎只需要一条记录:最大registrationNumber的记录。当您在任何记录集中查找一条记录时,应始终使用findOne()以最大限度地提高性能。

请参阅node.js实现中使用findOne的{​​{3}}详细信息,或参阅previous answer了解有关此收集方法的一般信息。