Mongoose / MongoDB更新无效

时间:2015-09-07 01:02:02

标签: node.js mongodb mongoose mongodb-query

我知道这个问题在这里被打死了,但我已经尝试了一切,无法解决这个问题。这让我很生气。

我的模型看起来像这样:

customer {
 email: String,
 password: String,
 addresses: [addresses_schema]
}

和addresses_schema看起来像

address {
 addr1: String,
 ... Other address fields
 primary_address: Boolean
}

现在,我想更新用户的特定地址记录,使primary_address为true。

所以我这样做:

var modifyUser = function(address_id){
  User.findOne( { email: email } ).then(function(user){
    user.update({ 'addresses._id': address_id }, 
                { $set: { 'addresses.$.primary_address': 'true' } } )

       .then(function(){
         console.log('Should eventually reach here');
        }).catch (err) {
           console.log('err:', err.message);
         });


    user.save();
  });
}

但是,如果我在更新之前和之后抓取user.addresses,则根本没有任何变化。相反,它给了我错误:

cannot use the part (addresses of addresses._id) to traverse the element ({addresses[ {addr1: '123 test street', addr2: '', city: 'test city' ... ]}

有人能帮助我吗?我真的很感激。谢谢!

2 个答案:

答案 0 :(得分:1)

我的资金将用在" address_id"你正在寻找的价值实际上并不匹配任何东西。在已审阅的文档上执行.update()通常不是您想要的,这会使代码中的问题混淆。

最初执行.findOneAndUpdate(),以便通过匹配的"电子邮件"和#34; addresses._id"在这个完整的例子中完成的值:

var async = require('async'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var addressSchema = new Schema({
  name: String,
  primary: { type: Boolean, default: false }
});

var userSchema = new Schema({
  email: String,
  addresses: [addressSchema]
});

var User = mongoose.model('User',userSchema);

mongoose.connect('mongodb://localhost/utest');

mongoose.set("debug",true);

async.series(
  [
    function(callback) {
      User.remove({},callback);
    },
    function(callback) {
      async.waterfall(
        [

          function(callback) {
            User.create({
              email: "example@example.com",
              addresses: [
                { "name": "One" },{ "name": "Two" }
              ]
            },callback)
          },

          function(user,callback) {
            console.log(user);
            User.findOneAndUpdate(
              {
                "email": user.email,
                "addresses._id": user.addresses[1]._id
              },
              {
                "$set": { "addresses.$.primary": true }
              },
              { "new": true }
            ).then(function(newUser) {
              console.log(newUser);
              callback();
            }).catch(function(err) {
              callback(err);
            });
          }
        ],
        callback
      )
    }
  ],
  function(err) {
    if (err) console.log(err.stack);
    mongoose.disconnect();
  }
);

这将始终如一地产生输出:

{ __v: 0,
  email: 'example@example.com',
  _id: 55ecf31a53558e183d208aa2,
  addresses:
   [ { name: 'One', _id: 55ecf31a53558e183d208aa4, primary: false },
     { name: 'Two', _id: 55ecf31a53558e183d208aa3, primary: false } ] }
{ _id: 55ecf31a53558e183d208aa2,
  email: 'example@example.com',
  __v: 0,
  addresses:
   [ { name: 'One', _id: 55ecf31a53558e183d208aa4, primary: false },
     { name: 'Two', _id: 55ecf31a53558e183d208aa3, primary: true } ] }

并且调试输出如下:

Mongoose: users.remove({}) {}
Mongoose: users.insert({ email: 'example@example.com', _id: ObjectId("55ecf35627cddb243d3d8e22"), addresses: [ { name: 'One', _id: ObjectId("55ecf35627cddb243d3d8e24"), primary: false }, { name: 'Two', _id: ObjectId("55ecf35627cddb243d3d8e23"), primary: false } ], __v: 0 })
Mongoose: users.findAndModify({ 'addresses._id': ObjectId("55ecf35627cddb243d3d8e23"), email: 'example@example.com' }) [] { '$set': { 'addresses.$.primary': true } } { new: true, upsert: false, remove: false }

这只是设置示例,但主要的事情发生在.findOneAndUpdate(),在承诺的解决方案中,您看到返回的文档为"更新"来自指定数组元素的原始形式。

这是你基本上应该在这里做的事情,对退回文件的任何进一步修改都来自""最初"更新和获取"已经完成了。

答案 1 :(得分:0)

我不知道你是否真的必须使用Mongoose,不知道这是否是你问题的要求。

以下是Monogodb直驱动器的示例:

var MongoClient = require('mongodb').MongoClient
  , format = require('util').format;

MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
if(err) throw err;

db.collection('test').findAndModify(
  {hello: 'world'}, // query
  [['_id','asc']],  // sort order
  {$set: {hi: 'there'}}, // replacement,     replaces only the field "hi"
  {}, // options
  function(err, object) {
      if (err){
          console.warn(err.message);  //     returns error if no matching object found
      }else{
          console.dir(object);
      }
  });
});