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

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

所以它基本上覆盖了req.body.profile所有profile ,我认为是有道理的。 有没有什么办法可以解决这个问题,而不必通过在更新查询中指定我的字段而不是req.body来更加明确?

你是正确的,mongoose转换更新为您$set 。 但是这并不能解决你的问题。 在mongodb shell中试试看,你会看到相同的行为。

相反,要更新一个深度嵌套属性,您需要指定$set的deep属性的完整path。

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

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对象。

我想你正在寻找$集

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

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

试试看

也许这是一个很好的解决scheme – 为Model.update添加选项,replace嵌套的对象,如:

{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,但是这些函数很容易被其他类似的东西替代