我有一个 post 路由,它接收来自 express 应用程序中的 PUT 请求的数据,该应用程序旨在根据提交的表单输入更新 mongoose 文档。 “基本”模型是 Profile
,我有两个 discriminator对 Helper
和 Finder
建模,它们有条件地将字段添加到 Profile
架构中(详见下文)。
因此,req.body.profile
将根据与其关联的鉴别器包含不同的字段,但始终包含字段(username
、email
city
, accountType
) 存在于“基本”模型中,Profile
。
在我发送 PUT 请求之前,Profile
中的文档示例如下所示:
{ jobTitle: '',
lastPosition: '',
email: '',
city: '',
accountType: 'helper',
_id: 5c77883d8db04c921db5f635,
username: 'here2help',
__v: 0 }
这对我来说看起来不错,并表明正在按照我的意愿创建模型(使用来自 Profile
的基本字段,以及与 Helper
模型关联的那些 - 请参阅下面是模型)。
我的 POST 路线如下所示:
router.put("/profile/:id", middleware.checkProfileOwnership, function(req, res){
console.log(req.body.profile);
Profile.findOneAndUpdate(req.params.id, req.body.profile, function(err, updatedProfile){
if(err){
console.log(err.message);
res.redirect("/profile");
} else {
console.log(updatedProfile);
res.redirect("/profile/" + req.params.id);
}
});
});
我从表单 (console.log(req.body.profile)
) 收到的信息是我希望看到的:
{ accountType: 'helper',
username: 'here2help',
email: 'helpingU@me.com',
city: 'New York',
jobTitle: 'CEO',
lastPosition: 'sales rep'}
但是,在 Profile.findOneAndUpdate()
中使用 req.body.profile
更新文档后,我没有看到我返回的文档更新:
console.log(updatedProfile)
{ jobTitle: '',
lastPosition: '',
email: 'helpingu@me.com',
city: 'New York',
accountType: 'helper',
_id: 5c77883d8db04c921db5f635,
username: 'here2help',
__v: 0 }
因此,在我的“基本”模型中定义的字段(即在 ProfileSchema
中定义的字段 - 见下文)正在更新(例如 city
),但那些在我的鉴别器中不是 - 见下文。
更新的信息清楚地存在于 req
中,但没有传播到 Profile
模型 - 这怎么可能?
我也尝试过使用 findByIdAndUpdate
但我得到了相同的结果。
这是我定义的模式:
个人资料 - 我的“基础”架构:
var mongoose = require("mongoose");
var passportLocalMongoose = require("passport-local-mongoose");
var profileSchema = new mongoose.Schema({
username: String,
complete: { type: Boolean, default: false },
email: { type: String, default: "" },
city: { type: String, default: "" }
}, { discriminatorKey: 'accountType' });
profileSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("Profile", profileSchema);
查找器
var Profile = require('./profile');
var Finder = Profile.discriminator('finder', new mongoose.Schema({
position: { type: String, default: "" },
skills: Array
}));
module.exports = mongoose.model("Finder");
助手
var Profile = require('./profile');
var Helper = Profile.discriminator('helper', new mongoose.Schema({
jobTitle: { type: String, default: "" },
lastPosition: { type: String, default: "" }
}));
module.exports = mongoose.model("Helper");
这是我第一次尝试使用 discriminators在 Mongoose 中,所以很可能是我设置不正确,这是问题的根源。
如果不清楚,请告诉我,或者我需要添加更多信息。
最佳答案
使用什么架构来查询数据库很重要
鉴别器根据您使用的对象构建 mongo 查询。例如,如果您使用 mongoose.set('debug', true)
在 mongo 上启用调试并运行 Profile.findOneAndUpdate(),您应该会看到如下内容:
Mongoose: profiles.findAndModify({
_id: ObjectId("5c78519e61f4b69da677a87a")
}, [], {
'$set': {
email: 'finder@me.com',
city: 'New York',
accountType: 'helper',
username: 'User NAme', __v: 0 } }, { new: true, upsert: false, remove: false, projection: {} })
请注意,它仅使用配置文件架构中定义的字段。
如果你使用 Helper,你会得到类似的东西:
profiles.findAndModify({
accountType: 'helper',
_id: ObjectId("5c78519e61f4b69da677a87a")
}, [], {
'$set': {
jobTitle: 'CTO',
email: 'finder@me.com',
city: 'New York',
accountType: 'helper ',
username: 'User Name', __v: 0 } }, { new: true, upsert: false, remove: false, projection: {} })
注意它在过滤条件中添加了鉴别器字段,这是documented :
Discriminator models are special; they attach the discriminator key to queries. In other words, find(), count(), aggregate(), etc. are smart enough to account for discriminators.
所以更新时需要做的是使用鉴别器字段,以便在调用更新语句时知道使用哪个Schema:
app.put("/profile/:id", function(req, res){
console.log(req.body);
if(ObjectId.isValid(req.params.id)) {
switch(req.body.accountType) {
case 'helper':
schema = Helper;
break;
case 'finder':
schema = Finder;
break;
default:
schema = Profile;
}
schema.findOneAndUpdate({ _id: req.params.id }, { $set : req.body }, { new: true, upsert: false, remove: {}, fields: {} }, function(err, updatedProfile){
if(err){
console.log(err);
res.json(err);
} else {
console.log(updatedProfile);
res.json(updatedProfile);
}
});
} else {
res.json({ error: "Invalid ObjectId"});
} });
请注意,在创建新文档时不需要上述内容,在这种情况下 mongoose 能够确定要使用哪个鉴别器。
您无法更新鉴别器字段
上述行为有副作用,您无法更新鉴别器字段,因为它不会找到记录。在这种情况下,您需要直接访问集合并更新文档,并定义属于另一个鉴别器的字段会发生什么。
db.profile.findOneAndUpdate({ _id: req.params.id }, { $set : req.body }, { new: true, upsert: false, remove: {}, fields: {} }, function(err, updatedProfile){
if(err) {
res.json(err);
} else {
console.log(updatedProfile);
res.json(updatedProfile);
}
});
关于javascript - findOneAndUpdate 中的文档未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54892850/