Mongoose 中的 lean() 方法能够提高性能,但它对查询结果有何影响?
在开发 Node.js 项目的过程中,Mongoose 是一个常用的 ODM(Object Data Mapping)框架,它允许开发者使用 JavaScript 语言操作 MongoDB 数据库。当数据量比较庞大时,查询性能将是一个问题。Mongoose 中的 lean() 方法能够提高查询性能,但要注意它对查询结果的影响。
lean() 方法是 Mongoose 用以获取原生 JavaScript 对象的方式。它可以较大地提高性能,因为不用依赖 Mongoose 的文档对象(Document对象)的 API,则无需花费时间进行转化。
当我们使用 lean() 方法时,查询的结果不是 Mongoose 的文档对象,而是纯粹的 JavaScript 对象。这代表着我们将会失去一些为文档对象准备的异步方法和一些 Mongoose 的内置虚拟属性。使用 lean() 方法可以省下这些内存占用,其中牺牲的部分是无法避免的。
使用示例:
假设我们在查询所有学生的信息以及它们所在班级的信息(类似于 JOIN 操作)。
我们可以使用下面的代码进行查询。
const mongoose = require('mongoose'); const StudentSchema = new mongoose.Schema({ name: { type: String, required: true }, age: { type: Number, required: true }, class: { type: mongoose.Types.ObjectId, ref: 'Class' } }); const ClassSchema = new mongoose.Schema({ name: { type: String, required: true }, location: { type: String, required: true } }); const StudentModel = mongoose.model('Student', StudentSchema); const ClassModel = mongoose.model('Class', ClassSchema); async function getStudents() { const students = await StudentModel.find().populate('class'); console.log(students); /* [ { "_id": "60603cc68f24281c7bf68d96", "name": "John", "age": 18, "class": { "_id": "60603d3f20e3f834cea11eaf", "name": "ClassA", "location": "Room 101", "__v": 0 }, "__v": 0 }, { "_id": "60603cca8f24281c7bf68d97", "name": "Jack", "age": 17, "class": { "_id": "60603d3f20e3f834cea11eaf", "name": "ClassA", "location": "Room 101", "__v": 0 }, "__v": 0 } ] */ }
在上面的代码中,我们使用了 populate() 方法,通过 class 属性中的 mongoose.Types.ObjectId 类型的 id 去访问 ClassModel,查询出 class 对象的信息。
但是当数据量变大时,查询时间会变得非常耗时,我们可以使用 lean() 方法代替 populate() 方法进行优化。
改进后的代码:
async function getStudents() { const students = await StudentModel.find().lean().populate({ path: 'class', select: ['name', 'location'] }); console.log(students); /* [ { "_id": "60603cc68f24281c7bf68d96", "name": "John", "age": 18, "class": { "_id": "60603d3f20e3f834cea11eaf", "name": "ClassA", "location": "Room 101" } }, { "_id": "60603cca8f24281c7bf68d97", "name": "Jack", "age": 17, "class": { "_id": "60603d3f20e3f834cea11eaf", "name": "ClassA", "location": "Room 101" } } ] */ }
我们可以看到,使用 lean() 方法的查询结果并不是文档对象,而是纯粹的 JavaScript 对象。在这个例子中,查询时间将会缩短。同时,我们可以通过 populate() 方法指定我们需要的属性,避免占用无用的内存。
需要注意的是,在使用 lean() 方法时,我们无法使用 findOneAndUpdate(),findOneAndDelete(),findByIdAndUpdate() 和 findByIdAndDelete() 等方法。因为它们都依赖于文档对象来保存查询结果。因此,在使用 lean() 方法时,可以考虑使用 updateOne() 和 deleteOne() 等原生的 MongoDB 方法。
总结:
lean() 方法是一个非常实用的查询优化方法,但是我们需要根据具体情况来考虑是否使用。在查询结果较大的时候,使用 lean() 方法将能够提升查询性能,同时我们需要注意到,使用 lean() 方法不能同时使用文档对象的一些异步方法和 Mongoose 的内置虚拟属性。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65b358beadd4f0e0ffc6880d