web-dev-qa-db-fra.com

Supprimer un champ de tous les éléments du tableau dans mongodb

J'ai ci-dessous le document dans 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"
}

Je veux supprimer withBase déposé des éléments du tableau à l'intérieur de casts.crew ..

J'ai essayé

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

rien n'a changé.

Et j'ai essayé ça ..

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

il a supprimé tout le tableau d'équipage du document.

Quelqu'un peut-il me fournir la bonne requête?

41
Nancy

Désolé de vous décevoir, mais votre réponse

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

n'est pas correcte. En fait, cela supprimera la valeur, MAIS uniquement à partir de la première occurrence du sous-document, en raison de la façon dont l'opérateur positionnel fonctionne :

l'opérateur positionnel $ agit comme un espace réservé pour le premier élément qui correspond au document de requête

Vous ne pouvez pas non plus utiliser $unset (comme vous l'avez essayé auparavant) car cela ne peut pas fonctionner sur les tableaux (et essayez-vous essentiellement de supprimer une clé d'un document du tableau). Vous ne pouvez pas non plus le supprimer avec $pull, car pull supprime tout le tableau, pas seulement un champ de celui-ci.

Par conséquent, pour autant que je sache, vous ne pouvez pas le faire avec un simple opérateur. Donc, le dernier recours fait $find puis forEach avec sauvegarde. Vous pouvez voir comment faire cela dans ma réponse ici . Dans votre cas, vous devez avoir une autre boucle dans la fonction forEach pour parcourir le tableau et supprimer une clé . J'espère que vous pourrez le modifier. Sinon, je vais essayer de vous aider.

P.S. Si quelqu'un cherche un moyen de le faire - voici la fonction de 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

Vous pouvez utiliser le nouveau positional identifier pour mettre à jour plusieurs éléments du tableau en 3.6.

Quelque chose comme

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

$ [] supprime toutes les propriétés withBase du tableau crews. Il agit comme un espace réservé pour la mise à jour de tous les éléments du tableau.

Utilisez multi true pour affecter plusieurs documents.

39
user2683814

J'ai trouvé un moyen de désinstaller ces listes sans avoir à récupérer l'objet (ce qui signifie, juste faire une mise à jour), c'est assez hackish mais si vous avez une énorme base de données, cela fera l'affaire:

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

En d'autres termes, vous devez calculer le nombre d'objets qu'il peut y avoir dans n'importe quelle liste de documents et ajouter explicitement ces nombres, dans ce cas comme {casts.crew.NUMBER.withBase: 1}.

De plus, pour compter le tableau le plus long dans un objet mongodb, un agrégat peut être fait, quelque chose comme ceci:

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

Je veux juste souligner que ce n'est pas une jolie solution mais bien plus rapide que la récupération et la sauvegarde.

13
Hassek