文档未在findOneAndUpdate中更新

fug*_*ugu 20 javascript mongoose mongodb node.js

我在快递应用程序中有一个POST路由,旨在根据提交的表单输入更新mongoose文档."基础"模型是Profile,我有两个鉴别器模型,HelperFinder有条件地向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)

  • 这非常有帮助,并且看起来可以按预期工作。 (2认同)