未在findOneAndUpdate

时间:2019-02-26 19:36:40

标签: javascript node.js mongodb mongoose

我有一个发布路线,该路线从Express应用程序中的PUT请求接收数据,该应用程序旨在根据提交的表单输入来更新猫鼬文档。 “基本”模型是Profile,我有两个HelperFinder模型,有条件地将字段添加到Profile模式。

因此,req.body.profile将包含不同的字段,具体取决于与之相关的标识符,但将始终包含以下字段(usernameemail 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,因此很有可能我没有正确设置它们,这是问题的根源。

如果不清楚,请让我知道,或者我需要添加更多信息。

2 个答案:

答案 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' }.覆盖文档