javascript - findOneAndUpdate 中的文档未更新

标签 javascript node.js mongodb mongoose

我有一个 post 路由,它接收来自 express 应用程序中的 PUT 请求的数据,该应用程序旨在根据提交的表单输入更新 mongoose 文档。 “基本”模型是 Profile,我有两个 discriminatorHelperFinder 建模,它们有条件地将字段添加到 Profile 架构中(详见下文)。

因此,req.body.profile 将根据与其关联的鉴别器包含不同的字段,但始终包含字段(usernameemail 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/

相关文章:

javascript - 在纯 Javascript 中获取复选框 onclick 的 ID 或值

javascript - 如何更改模板字符串推断的值

sql - 如何用 "like"查询MongoDB

mongodb - 如何查找集合中每个ID的最新版本文档?

javascript - 将 onchange 事件监听器添加到 html 输入字段

javascript - 为什么 console.log() 创建/**id :4**/and/**ref:4**/values?

node.js - 在 Kubernetes 中将 secret 作为环境变量访问

android - ionic 1、 ionic 和 ionic 3 之间有什么区别? ionic 2 和 ionic3 是一样的吗?

mongodb - Node.js 和 Mongodb - TypeError : undefined is not a function

php - CodeMirror 保存自己 onBlur