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

Remove a field from all elements in array in mongodb

本问题已经有最佳答案,请猛点这里访问。

我有以下MongoDB文档(2.4.5)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
   "_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文件。

我试过这个

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

没有改变。

尝试过这个……

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

它从文档中删除了整个地震队阵列。

有人能为我提供正确的查询吗?


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

1
2
3
4
5
6
7
8
db.coll.update({
   _id:235399,
  "casts.crew.withBase": {$exists: true}
},{
   $unset: {
     "casts.crew.$.withBase" : true
   }
},false,true)

不正确。实际上,由于位置运算符的工作方式,它将移除该值,但仅从子文档的第一个出现处移除:

the positional $ operator acts as a placeholder for the first element
that matches the query document

您也不能使用$unset(如您之前所尝试的那样),因为它不能在数组上工作(并且您基本上是在尝试从数组中删除文档中的键)。您也不能用$pull删除它,因为pull会删除所有数组,而不仅仅是其中的一个字段。

因此,据我所知,你不能用一个简单的算符来做这个。因此,最后一个办法是先实施$find,然后实施forEach,再实施save。你可以在我的回答中看到怎么做。在您的例子中,需要在forEach函数中有另一个循环来遍历数组和删除键。我希望你能修改它。如果没有,我会尽力帮助你。

另外,如果有人想办法做到这一点,这是桑德拉的功用

1
2
3
4
5
6
7
8
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);
});


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

类似的东西

1
 db.coll.update( {_id:235399}, {$unset: {"casts.crew.$[].withBase":""}} )

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

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


我发现了一种不用拉上对象就可以取消设置列表的方法(也就是说,只需进行一次更新),这非常简单,但是如果你有一个庞大的数据库,它将完成交易:

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

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

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

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

只是想强调一下,这不是一个很好的解决方案,但比提取和保存要快得多。