我有一个发布路线,该路线从Express应用程序中的PUT请求接收数据,该应用程序旨在根据提交的表单输入来更新猫鼬文档。 “基本”模型是Profile
,我有两个Helper
和Finder
模型,有条件地将字段添加到Profile
模式。
因此,req.body.profile
将包含不同的字段,具体取决于与之相关的标识符,但将始终包含以下字段(username
,email
city
,{{1} })存在于“基本”模型accountType
中。
在我发送PUT请求之前,Profile
中的文档示例如下所示:
Profile
这对我来说看起来不错,并建议根据需要创建模型(使用{ jobTitle: '',
lastPosition: '',
email: '',
city: '',
accountType: 'helper',
_id: 5c77883d8db04c921db5f635,
username: 'here2help',
__v: 0 }
中的基础字段以及与Profile
模型相关的基础字段-有关模型,请参见下文)。
然后我的POST路由如下:
Helper
我期望从表单(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'}
中使用req.body.profile
更新文档后,我看不到返回的文档已更新:
Profile.findOneAndUpdate()
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");
这是我第一次尝试在猫鼬中使用discriminator,因此很有可能我没有正确设置它们,这是问题的根源。
如果不清楚,请让我知道,或者我需要添加更多信息。
答案 0 :(得分:10)
使用哪种模式查询数据库很重要
鉴别器根据您使用的对象构建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: {} })
请注意,它仅使用Profile模式中定义的字段。
如果使用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:
鉴别器模型很特殊;他们将区分键附加到查询。换句话说,find(),count(),aggregate()等足够聪明,足以说明区分符。
因此,更新时您需要做的是使用discriminator字段,以便知道在调用update语句时要使用哪种架构:
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"});
} });
注意,创建新文档时不需要上面的内容,在这种情况下,猫鼬可以确定要使用的区分符。
您无法更新区分字段
以上行为有一个副作用,您无法更新鉴别符字段,因为它将找不到记录。在这种情况下,您将需要直接访问集合并更新文档,并定义属于另一个区分符的字段将发生什么。
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);
}
});
答案 1 :(得分:0)
在Moongose findOneAndUpdate()
中,方法具有四个参数
像
A.findOneAndUpdate(conditions, update, options, callback) // executes
您需要像这样执行
var query = { name: 'borne' };
Model.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)
甚至
// is sent as
Model.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)
这有助于防止意外地用{ name: 'jason bourne' }.
覆盖文档