web-dev-qa-db-ja.com

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)

ドキュメントからクルー配列全体を削除しました。

誰かが私に正しいクエリを提供してもらえますか?

41
Nancy

失望して申し訳ありませんが、あなたの答え

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

正しくありません。実際には、値が削除されますが、サブドキュメントの最初の出現からのみ削除されます。これは、 位置演算子が機能する

位置$演算子は、クエリドキュメントに一致する最初の要素のプレースホルダーとして機能します

また、$unset(以前に試したように)を使用することはできません。これは、配列で機能しないためです(基本的に、配列からドキュメントからキーを削除しようとしています)。また、プルはフィールドだけでなくすべての配列を削除するため、$pullで削除することもできません。

したがって、私が知る限り、単純な演算子でこれを行うことはできません。したがって、最後の手段は、$findを実行してから、forEachを保存して実行することです。 ここでの私の回答でこれを行う方法 を見ることができます。あなたの場合、forEach関数に別のループを作成して、配列を繰り返し処理し、 キーを削除 する必要があります。あなたがそれを修正できることを願っています。いいえの場合、私はあなたを助けようとします。

追伸誰かがこれを行う方法を探している場合-ここに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);
});
46
Salvador Dali

新しい positional identifier 3.6で配列の複数の要素を更新します。

何かのようなもの

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

$ [] は、withBase配列からすべてのcrewsプロパティを削除します。配列内のすべての要素を更新するためのプレースホルダーとして機能します。

複数のドキュメントに影響を与えるには、trueを使用します。

39
user2683814

オブジェクトをプルアップせずにこのリストの設定を解除する方法を見つけました(つまり、更新するだけです)、それはかなりハックですが、巨大なデータベースがある場合は対処します:

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} )

これはきれいな解決策ではなく、取得して保存するよりもはるかに高速であることを強調したいだけです。

13
Hassek