当前位置:  开发笔记 > 编程语言 > 正文

Mongoose.js:嵌套属性的原子更新?

如何解决《Mongoose.js:嵌套属性的原子更新?》经验,为你挑选了2个好方法。

使用Mongoose版本3.6.4

假设我有一个像这样的MongoDB文档:

{
    "_id" : "5187b74e66ee9af96c39d3d6",
    "profile" : {
        "name" : {
            "first" : "Joe",
            "last" : "Pesci",
            "middle" : "Frank"
        }
    }
}

我为用户提供以下架构:

var UserSchema = new mongoose.Schema({
  _id:    { type: String },
  email:  { type: String, required: true, index: { unique: true }},
  active: { type: Boolean, required: true, 'default': false },
  profile: {
    name: {
      first:    { type: String, required: true },
      last:     { type: String, required: true },
      middle:   { type: String }
    }
  }
  created:    { type: Date, required: true, 'default': Date.now},
  updated:    { type: Date, required: true, 'default': Date.now}
);

然后我提交一个表单,传递一个名为的字段:profile[name][first]值为Joseph

因此我想只更新用户的名字,但留下他的最后和中间人,我想我会这样做:

User.update({email: "joe@foo.com"}, req.body, function(err, result){});

但是当我这样做时,它会"删除" profile.name.lastprofile.name.middle属性,最终会得到一个看起来像这样的文档:

{
    "_id" : "5187b74e66ee9af96c39d3d6",
    "profile" : {
        "name" : {
            "first" : "Joseph"
        }
    }
}

所以基本上覆盖所有的profilereq.body.profile,我想是有道理的.有没有办法绕过它而不必通过在更新查询中指定我的字段而不是更明确而不是req.body



1> aaronheckman..:

你是对的,Mongoose $set为你转换更新.但这并不能解决您的问题.在mongodb shell中尝试一下,你会看到相同的行为.

相反,要更新单个深层嵌套的属性,您需要指定深层属性的完整路径$set.

User.update({ email: 'joe@foo.com' }, { 'profile.name.first': 'Joseph' }, callback)


是的,但我希望我能传入`req.body`所以我没有必要指定所有可能的字段.所以我最后做一个`findById()`,首先从找到的doc中删除`__v`和`_id`,使用`_.deepExtend()`合并新的更新属性,然后将我的frankenstein对象传递给Mongoose的`update`.

2> Stefan..:

一个非常简单的方法来解决这个Moongose 4.1flat包:

var flat = require('flat'),
    Schema = mongoose.Schema,
        schema = new Schema(
            {
                name: {
                    first: {
                        type: String,
                        trim: true
                    },
                    last: {
                        type: String,
                        trim: true
                    }
                }
            }
        );

    schema.pre('findOneAndUpdate', function () {
        this._update = flat(this._update);
    });


    mongoose.model('User', schema);

req.body (例如)现在可以是:

{
    name: {
        first: 'updatedFirstName'
    }
}

在执行实际查询之前,对象将被展平,因此$set将仅更新期望的属性而不是整个name对象.

推荐阅读
yzh148448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有