从mongodb中的数组中的所有元素中删除一个字段

时间:2013-11-13 05:20:52

标签: arrays mongodb

我在MongoDB(2.4.5)中有以下文档

{
    "_id" : 235399,
    "casts" : {
        "crew" : [ 
            {
                "_id" : 1186343,
                "withBase" : true,
                "department" : "Directing",
                "job" : "Director",
                "name" : "Connie Rasinski"
            },
            {
                "_id" : 86342,
                "withBase" : true
            }
        ]
    },
    "likes" : 0,
    "rating" : 0,
    "rating_count" : 0,
    "release_date" : "1955-11-11"
}

我想从casts.crew ..

中的数组元素中删除withBase

我试过这个

db.coll.update({_id:235399},{$unset: {  "casts.crew.withBase" : 1 } },false,true)
没有改变。

并尝试了这个..

db.coll.update({_id:235399},{$unset: {  "casts.crew" : { $elemMatch: { "withBase": 1 } } } },false,true)

它从文档中删除了整个工作人员阵列。

有人可以提供正确的查询吗?

3 个答案:

答案 0 :(得分:44)

很抱歉让你失望,但你的回答

db.coll.update({
   _id:235399,
   "casts.crew.withBase": {$exists: true}
},{
   $unset: {
      "casts.crew.$.withBase" : true
   }
},false,true)

不正确。实际上它会删除值,但仅从第一次出现的子文档中删除,因为positional operator works的方式:

  

位置$运算符充当第一个元素的占位符   与查询文档匹配

您也无法使用$unset(正如您之前尝试过的那样),因为它无法在数组上运行(您基本上是尝试从数组中删除文档中的键)。你也无法用$pull删除它,因为pull会删除所有数组,而不仅仅是它的一个字段。

因此据我所知,你不能用一个简单的算子来做到这一点。所以最后的办法是$find,然后forEach进行保存。你可以看到how to do this in my answer here。在您的情况下,您需要在forEach函数中使用另一个循环来迭代数组并转到delete a key。我希望你能修改它。如果不是,我会尽力帮助你。

P.S。如果有人想要这样做 - 这里是 Sandra的功能

db.coll.find({_id:235399}).forEach( function(doc) {
  var arr = doc.casts.crew;
  var length = arr.length;
  for (var i = 0; i < length; i++) {
    delete arr[i]["withBase"];
  }
  db.coll.save(doc);
});

答案 1 :(得分:29)

您可以使用新的positional identifier更新3.6中的数组中的多个元素。

这样的东西
 db.coll.update( {_id:235399}, {$unset: {"casts.crew.$[].withBase":""}} )

$[]withBase数组中删除所有crews属性。它充当占位符,用于更新数组中的所有元素。

使用multi true可影响多个文档。

答案 2 :(得分:13)

我找到了一种方法来取消设置这个列表,而不必拉起对象(意思是,只是做一次更新),这是非常hackish但是如果你有一个庞大的数据库它将会达成协议:

db.coll.update({},{$unset: {"casts.crew.0.withBase" : 1, "casts.crew.1.withBase" : 1} }, {multi: 1})

换句话说,您必须计算任何文档列表中可以有多少个对象,并明确添加这些数字,在本例中为{casts.crew.NUMBER.withBase: 1}

另外,要计算mongodb对象中最长的数组,可以进行聚合,如下所示:

db.coll.aggregate( [   { $unwind : "$casts.crew" },   { $group : { _id : "$_id", len : { $sum : 1 } } },   { $sort : { len : -1 } },   { $limit : 1 } ], {allowDiskUse: true} )

只是想强调这不是一个漂亮的解决方案,但比获取和保存更快。