2013-02-08 57 views
24

我的模型文档中有一个数组。我想根据我提供的密钥删除该数组中的元素,然后更新MongoDB。这可能吗?Mongoose删除文档中的数组元素并保存

这里是我的尝试:

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

var favorite = new Schema({ 
    cn: String, 
    favorites: Array 
}); 

module.exports = mongoose.model('Favorite', favorite, 'favorite'); 

exports.deleteFavorite = function (req, res, next) { 
    if (req.params.callback !== null) { 
     res.contentType = 'application/javascript'; 
    } 
    Favorite.find({cn: req.params.name}, function (error, docs) { 
     var records = {'records': docs}; 
     if (error) { 
      process.stderr.write(error); 
     } 
     docs[0]._doc.favorites.remove({uid: req.params.deleteUid}); 

     Favorite.save(function (error, docs) { 
      var records = {'records': docs}; 
      if (error) { 
       process.stderr.write(error); 
      } 
      res.send(records); 

      return next(); 
     }); 
    }); 
}; 

到目前为止发现的文件,但移除也不会保存作品。

回答

51

您也可以直接在MongoDB中进行更新,而无需加载文档并使用代码进行修改。使用$pull$pullAll运营商从数组中删除的项目:

Favorite.update({cn: req.params.name}, { $pullAll: {uid: [req.params.deleteUid] } }) 

http://docs.mongodb.org/manual/reference/operator/update/pullAll/

+2

这对性能来说更好。 –

+1

非常有帮助,谢谢。 – Nate

+1

谢谢你的工作 – Dibish

5

由于收藏夹是一个数组,因此您只需将其拼接并保存文档即可。

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

var favorite = new Schema({ 
    cn: String, 
    favorites: Array 
}); 

module.exports = mongoose.model('Favorite', favorite); 

exports.deleteFavorite = function (req, res, next) { 
    if (req.params.callback !== null) { 
     res.contentType = 'application/javascript'; 
    } 
    // Changed to findOne instead of find to get a single document with the favorites. 
    Favorite.findOne({cn: req.params.name}, function (error, doc) { 
     if (error) { 
      res.send(null, 500); 
     } else if (doc) { 
      var records = {'records': doc}; 
      // find the delete uid in the favorites array 
      var idx = doc.favorites ? doc.favorites.indexOf(req.params.deleteUid) : -1; 
      // is it valid? 
      if (idx !== -1) { 
       // remove it from the array. 
       doc.favorites.splice(idx, 1); 
       // save the doc 
       doc.save(function(error) { 
        if (error) { 
         console.log(error); 
         res.send(null, 500); 
        } else { 
         // send the records 
         res.send(records); 
        } 
       }); 
       // stop here, otherwise 404 
       return; 
      } 
     } 
     // send 404 not found 
     res.send(null, 404); 
    }); 
}; 
+0

谢谢你的回应。 – occasl

+3

如果您尝试同时删除2件东西,则它们都可能会得到该数组,然后将其更改,并且第一次保存的更改会被第二次覆盖。我宁愿像这样http://stackoverflow.com/questions/16959099/how-to-remove-array-element-in-mongodb。 – Maximosaic

29

选中的答案的工作,但正式MongooseJS最新的,你应该使用

doc.subdocs.push({ _id: 4815162342 }) // added 
doc.subdocs.pull({ _id: 4815162342 }) // removed 

http://mongoosejs.com/docs/api.html#types_array_MongooseArray-pull

我只是在寻找的是太多。

查看Daniel的正确答案的答案。好多了。

0
keywords = [1,2,3,4]; 
doc.array.pull(1) //this remove one item from a array 
doc.array.pull(...keywords) // this remove multiple items in a array 

,如果你想使用...你应该在你的js文件的顶部调用'use strict';; :)

1

这对我而言非常有帮助。

SubCategory.update({ _id: { $in: 
     arrOfSubCategory.map(function (obj) { 
      return mongoose.Types.ObjectId(obj); 
     }) 
    } }, 
    { 
     $pull: { 
      coupon: couponId, 
     } 
    }, { multi: true }, function (err, numberAffected) { 
     if(err) { 
      return callback({ 
       error:err 
      }) 
     } 
    }) 
}); 

我有一个模型,它的名字是SubCategory,我想从这一类Array中优惠券。我有一系列的类别,所以我使用了arrOfSubCategory。所以我用$in运算符的帮助下,用map函数从这个数组中取出每个对象数组。