我正在使用一个名为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
字段上已有索引。
答案 0 :(得分:4)
then()
快速执行但find()
需要一段时间才有意义;在一组记录中找到最大值是一个相对快速的数据库操作,而获取该集合可能非常耗时,具体取决于许多因素。
如果您只是通过REST或某种可视界面阅读数据并将其呈现给用户,您可以使用lean()
来返回普通的javascript对象。默认情况下,您返回一个mongoose.Document
,在您的情况下是不必要的,因为在您的读取查询后似乎没有任何数据操作;你刚收到数据。
更重要的是,您似乎只需要一条记录:最大registrationNumber
的记录。当您在任何记录集中查找一条记录时,应始终使用findOne()
以最大限度地提高性能。
请参阅node.js实现中使用findOne
的{{3}}详细信息,或参阅previous answer了解有关此收集方法的一般信息。