fug*_*ugu 20 javascript mongoose mongodb node.js
我在快递应用程序中有一个POST路由,旨在根据提交的表单输入更新mongoose文档."基础"模型是Profile,我有两个鉴别器模型,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 }
Run Code Online (Sandbox Code Playgroud)
这看起来对我来说很好,并建议我正在创建模型(使用基本字段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);
}
});
});
Run Code Online (Sandbox Code Playgroud)
我从表单(console.log(req.body.profile))收到的信息是我期望看到的:
{ accountType: 'helper',
username: 'here2help',
email: 'helpingU@me.com',
city: 'New York',
jobTitle: 'CEO',
lastPosition: 'sales rep'}
Run Code Online (Sandbox Code Playgroud)
之后req.body.profile:
Profile.findOneAndUpdate()
{ jobTitle: '',
lastPosition: '',
email: 'helpingu@me.com',
city: 'New York',
accountType: 'helper',
_id: 5c77883d8db04c921db5f635,
username: 'here2help',
__v: 0 }
Run Code Online (Sandbox Code Playgroud)
因此,我的"基础"模型中定义的字段(即在console.log(updatedProfile)下面定义的那些字段)正在更新,但是我的鉴别器中的字段不是 - (参见下面和我的相关问题).
更新后的信息显然存在于模型中ProfileSchema,但未传播到city模型中 - 这怎么可能?
我也尝试过使用req但是得到了相同的结果.
以下是我定义的模式:
个人资料 - 我的"基础"架构:
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);
Run Code Online (Sandbox Code Playgroud)
发现者
var Profile = require('./profile');
var Finder = Profile.discriminator('finder', new mongoose.Schema({
position: { type: String, default: "" },
skills: Array
}));
module.exports = mongoose.model("Finder");
Run Code Online (Sandbox Code Playgroud)
帮手
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");
Run Code Online (Sandbox Code Playgroud)
这是我第一次尝试在mongoose 中使用鉴别器,所以我更有可能错误地设置它们,而这是问题的根源.
如果不清楚,请告诉我,或者我需要添加更多信息.
Cri*_*ado 11
您使用什么模式查询数据库很重要
鉴别器根据您使用的对象构建mongo查询.例如,如果在mongo上启用调试mongoose.set('debug', true)并运行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: {} })
Run Code Online (Sandbox Code Playgroud)
请注意,它仅使用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: {} })
Run Code Online (Sandbox Code Playgroud)
请注意,它在过滤条件中添加了discriminator字段,这是 记录的:
鉴别器模型很特别; 他们将鉴别器密钥附加到查询中.换句话说,find(),count(),aggregate()等足够聪明,可以说明鉴别器.
因此,更新时需要做的是使用discriminator字段以便在调用update语句时知道要使用哪个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"});
} });
Run Code Online (Sandbox Code Playgroud)
注意,在创建新文档时上面没有必要,在那种情况下,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);
}
});
Run Code Online (Sandbox Code Playgroud)