Mongoose 是 Node.js 环境下的 MongoDB 驱动程序,它的 Schema 是用于定义 MongoDB 中文档数据结构的一种方式。在实际开发中,我们经常会使用 Mongoose 来操作 MongoDB 数据库。但是,在定义 Schema 时,我们可能会遇到一些陷阱,这篇文章将会详细介绍这些陷阱,并提供解决方法和示例代码。
陷阱一:默认值的陷阱
在 Mongoose 中,我们可以为 Schema 中的字段设置默认值。例如,下面的代码定义了一个 Schema,其中字段 age
的默认值为 18:
const userSchema = new mongoose.Schema({ name: String, age: { type: Number, default: 18 } });
然而,如果我们在创建文档时没有指定 age
的值,那么 age
字段的值并不会被设置为默认值,而是会被设置为 undefined
。这是因为 Mongoose 会认为 undefined
是一个有效值,所以它不会将默认值赋值给 age
字段。
解决方法是,在创建文档时手动为 age
字段赋值。例如:
const user = new User({ name: 'Alice' }); user.age = user.age || 18; user.save();
陷阱二:虚拟字段的陷阱
虚拟字段是指在 Schema 中定义的,但是在 MongoDB 中并不存在的字段。虚拟字段通常用于计算或展示文档中的某些值。例如,下面的代码定义了一个虚拟字段 fullName
,它的值是 firstName
和 lastName
字段的拼接结果:
const userSchema = new mongoose.Schema({ firstName: String, lastName: String }); userSchema.virtual('fullName').get(function() { return `${this.firstName} ${this.lastName}`; });
然而,当我们使用 find()
方法查询文档时,虚拟字段 fullName
并不会被返回。这是因为虚拟字段并不是 MongoDB 文档中的一部分,所以它不会被查询出来。
解决方法是,在查询文档时使用 lean()
方法,并将其设置为 true
。这样,Mongoose 将会返回一个普通的 JavaScript 对象,而不是 Mongoose 文档对象。例如:
User.find().lean().exec(function(err, users) { console.log(users[0].fullName); });
陷阱三:数组默认值的陷阱
在 Mongoose 中,我们可以为数组字段设置默认值。例如,下面的代码定义了一个 Schema,其中字段 hobbies
的默认值为空数组:
const userSchema = new mongoose.Schema({ name: String, hobbies: { type: [String], default: [] } });
然而,如果我们在创建文档时没有指定 hobbies
的值,那么 hobbies
字段的值并不会被设置为默认值,而是会被设置为 null
。这是因为 Mongoose 会认为 null
是一个有效值,所以它不会将默认值赋值给 hobbies
字段。
解决方法是,在创建文档时手动为 hobbies
字段赋值。例如:
const user = new User({ name: 'Alice' }); user.hobbies = user.hobbies || []; user.save();
陷阱四:Schema 嵌套的陷阱
在 Mongoose 中,我们可以在 Schema 中嵌套另一个 Schema。例如,下面的代码定义了一个嵌套的 Schema,它表示一个学生的成绩信息:
-- -------------------- ---- ------- ----- ----------- - --- ----------------- ----- ------- -------- ------ --- ----- ------------- - --- ----------------- ----- ------- ------ ----------- ---
然而,当我们查询文档时,嵌套的 Schema 并不会被自动填充。例如,下面的代码查询了一个学生的信息,但是它的成绩信息并没有被填充:
Student.findOne({ name: 'Alice' }, function(err, student) { console.log(student.score); // 输出 undefined });
解决方法是,在查询文档时使用 populate()
方法,并将其参数设置为嵌套的 Schema 的字段名。例如:
Student.findOne({ name: 'Alice' }).populate('score').exec(function(err, student) { console.log(student.score.math); // 输出数学成绩 });
总结
本文介绍了 Mongoose Schema 定义中的四个陷阱,并提供了相应的解决方法和示例代码。这些陷阱虽然看起来很小,但是在实际开发中可能会给我们带来麻烦。希望本文能够帮助读者更好地理解 Mongoose Schema 的使用。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/65e3dcc41886fbafa401f6ca