1. 简介
在使用MongoDB数据库时,Mongoose是一个非常流行的ORM库。可以通过Mongoose将MongoDB转换成具有模型层的数据库。但是,在使用Mongoose过程中,我们会遇到一些问题,特别是在对象创建和更新过程中。其中一个常见的问题是,在从Mongoose得到的对象中增加自定义属性时,该属性始终为undefined。这篇文章将介绍两种解决方法。
2. 问题描述
当我们从Mongoose得到一个对象时,这个对象是一个Mongoose模型的实例。当我们尝试为这个对象添加自定义属性时,我们会发现这个新属性不能被正确保存到数据库中。以下是一个简单的例子:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: String,
email: String
});
const User = mongoose.model("User", UserSchema);
const user = new User({
name: "Alice",
email: "alice@example.com"
});
user.phoneNumber = "555-1234";
user.save().then(() => console.log("User saved!"));
这将会输出"User saved!",但是phoneNumber属性并没有被保存到数据库中。
3. 解决方法一
3.1 Object.assign()
一种解决方法是使用JavaScript中的Object.assign()方法,将Mongoose对象转换成普通JavaScript对象并在此对象上添加属性。这个新的JavaScript对象可以直接被保存到MongoDB数据库中。
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: String,
email: String
});
const User = mongoose.model("User", UserSchema);
const user = new User({
name: "Alice",
email: "alice@example.com"
});
const userObj = user.toObject();
userObj.phoneNumber = "555-1234";
User.update({ _id: user.id }, userObj).then(() => console.log("User saved!"));
在上面的代码中,我们首先使用user.toObject()将Mongoose对象转换成普通JavaScript对象。然后我们在这个新的JavaScript对象上添加一个phoneNumber属性。最后,我们使用MongoDB的update方法将这个新的JavaScript对象保存到数据库中。
3.2 toJSON()
另一种解决方法是使用Mongoose中的toJSON()方法,将一个Mongoose对象转换为一个普通的JavaScript对象。这个新的JavaScript对象可以直接被保存到MongoDB数据库中。
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: String,
email: String
});
const User = mongoose.model("User", UserSchema);
const user = new User({
name: "Alice",
email: "alice@example.com"
});
const userObj = user.toJSON();
userObj.phoneNumber = "555-1234";
User.update({ _id: user.id }, userObj).then(() => console.log("User saved!"));
在上面的代码中,我们首先使用user.toJSON()将Mongoose对象转换成普通JavaScript对象。接着我们在这个新的JavaScript对象上添加一个phoneNumber属性。最后,我们使用MongoDB的update方法将这个新的JavaScript对象保存到数据库中。
4. 解决方法二
4.1 Mongoose Schema 预设属性 .set()
另一种解决该问题的方法是使用Mongoose的预设属性 .set()。使用这个方法可以让我们在添加新的属性时不需要使用toJSON()或者Object.assign()方法。
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: String,
email: String
});
UserSchema.set("toObject", {
virtuals: true,
transform: function(doc, ret, options) {
ret.id = ret._id;
delete ret._id;
delete ret.__v;
}
});
const User = mongoose.model("User", UserSchema);
const user = new User({
name: "Alice",
email: "alice@example.com"
});
user.phoneNumber = "555-1234";
user.save().then(() => console.log("User saved!"));
在上面的代码中,我们使用UserSchema.set()方法为我们的UserSchema添加了一个toObject预设属性。这个预设属性告诉Mongoose将虚拟属性(virtuals)赋值给新的JavaScript对象,并且使用transform函数删除不需要的属性。这意味着当我们添加自定义属性时,这些属性将被包含在Mongoose对象的toObject()和toJSON()方法中,并正确地保存到数据库中。
4.2 Mongoose Schema 预设属性 .virtual()
另一个方法是使用Mongoose的预设属性 .virtual()。使用这个方法我们可以在Mongoose对象中添加虚拟属性,这些属性将包含在Mongoose对象的toObject()和toJSON()方法中,并且正确地保存到数据库中。
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: String,
email: String,
phoneNumber: {
type: String,
virtual: true,
set: function (value) {
this._phoneNumber = value;
},
get: function() {
return this._phoneNumber;
}
}
});
const User = mongoose.model("User", UserSchema);
const user = new User({
name: "Alice",
email: "alice@example.com"
});
user.phoneNumber = "555-1234";
user.save().then(() => console.log("User saved!"));
在上面的代码中,我们使用UserSchema.virtual()方法为Mongoose模式添加虚拟属性phoneNumber。这个属性在Mongoose对象中的名称是_phoneNumber。我们使用set()方法将值存储在_phoneNumber属性中,并使用get()方法取回值。最后,我们将phoneNumber设置为"555-1234"并将用户对象保存到数据库中。
5. 结论
本文介绍了四种解决在Mongoose中添加自定义属性不被正确保存到数据库中的方法。第一种是使用toJSON()和Object.assign()方法。第二种是使用Mongoose Schema的预设属性.set()和预设属性.virtual()。每种方法都有其优点和缺点,可以根据具体情况进行选择。希望本文能够帮助您在使用Mongoose时正确地添加自定义属性。