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

Nan*_*ncy 43 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"
}
Run Code Online (Sandbox Code Playgroud)

我想从casts.crew中的数组元素中删除withBase.

我试过这个

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

没有改变.

并试过这个..

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

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

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

Sal*_*ali 48

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

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

是不正确的.实际上它将删除值,但仅从第一次出现的子文档中删除,因为位置运算符的工作方式:

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

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

因此,据我所知,你不能用一个简单的运算符来做到这一点.所以最后的手段是做$find,然后forEach保存.你可以在我的答案中看到如何做到这一点.在你的情况下,你需要在forEach函数中有另一个循环来迭代数组并删除一个键.我希望你能修改它.如果不是,我会尽力帮助你.

PS如果有人想要这样做 - 这是桑德拉的功能

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);
});
Run Code Online (Sandbox Code Playgroud)


use*_*814 42

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

就像是

 db.coll.update( {_id:235399}, {$unset: {"casts.crew.$[].withBase":""}} )
Run Code Online (Sandbox Code Playgroud)

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

使用multi true可以影响多个文档.

  • 请不要在没有解释的情况下进行投票.很乐意解决您的疑虑. (2认同)
  • 对不起,我投了反对票,我不能取消投反对票:) - 这实际上_确实_有效,但仅适用于 mongodb &gt;=3.6。它也适用于`updateMany()` (2认同)

Has*_*sek 13

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

db.coll.update({},{$unset: {"casts.crew.0.withBase" : 1, "casts.crew.1.withBase" : 1} }, {multi: 1})
Run Code Online (Sandbox Code Playgroud)

换句话说,您必须计算任何文档列表中可以有多少个对象,并明确添加这些数字,在本例中为{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} )
Run Code Online (Sandbox Code Playgroud)

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