19

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"
        }
    }
}

したがって、基本的にはすべてをprofilewithreq.body.profileで上書きしていますが、これは理にかなっていると思います。の代わりに更新クエリで自分のフィールドを指定することで、より明示的にする必要なく、それを回避する方法はありますreq.bodyか?

4

4 に答える 4

20

その通りです。Mongoose は更新を に変換$setします。しかし、これはあなたの問題を解決しません。mongodb シェルで試してみると、同じ動作が見られます。

代わりに、深くネストされた単一のプロパティを更新するには、$set.

User.update({ email: 'joe@foo.com' }, { 'profile.name.first': 'Joseph' }, callback)
于 2013-05-08T16:47:05.567 に答える
11

パッケージを使用しMoongose 4.1てこれを解決する非常に簡単な方法の 1 つ:flat

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ます。

于 2015-07-28T17:48:21.283 に答える
0

$set を探していると思います

http://docs.mongodb.org/manual/reference/operator/set/

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

それを試してみてください

于 2013-05-06T14:45:59.110 に答える
0

多分それは良い解決策です-Model.updateにオプションを追加して、ネストされたオブジェクトを次のように置き換えます。

{field1: 1, fields2: {a: 1, b:2 }} => {'field1': 1, 'field2.a': 1, 'field2.b': 2}

  nestedToDotNotation: function(obj, keyPrefix) {
    var result;
    if (keyPrefix == null) {
      keyPrefix = '';
    }
    result = {};
    _.each(obj, function(value, key) {
      var nestedObj, result_key;
      result_key = keyPrefix + key;
      if (!_.isArray(value) && _.isObject(value)) {
        result_key += '.';
        nestedObj = module.exports.nestedToDotNotation(value, result_key);
        return _.extend(result, nestedObj);
      } else {
        return result[result_key] = value;
      }
    });
    return result;
  }

});

循環参照の処理を改善する必要がありますが、これはネストされたオブジェクトを操作するときに非常に便利です

ここでは underscore.js を使用していますが、これらの関数は他のアナログに簡単に置き換えることができます

于 2014-03-20T10:58:28.007 に答える