Supprimer une clé d'un document MongoDB à l'aide de Mongoose

103

J'utilise la bibliothèque Mongoose pour accéder à MongoDB avec node.js

Existe-t-il un moyen de supprimer une clé d'un document ? c'est à dire non seulement définir la valeur à null, mais le supprimer?

User.findOne({}, function(err, user){
  //correctly sets the key to null... but it's still present in the document
  user.key_to_delete = null;

  // doesn't seem to have any effect
  delete user.key_to_delete;

  user.save();
});
Daniel Beardsley
la source
1
Je pensais l'avoir trouvé, mais après quelques tests: probablement pas. Cela a cependant une bonne discussion sur le sujet. groups.google.com/group/mongoose-orm/browse_thread/thread/…
Stephen
LOL tant pis, je suppose que c'était ton message!
Stephen

Réponses:

168

Dans les premières versions, vous auriez dû supprimer le pilote natif de node-mongodb. Chaque modèle a un objet de collection qui contient toutes les méthodes proposées par node-mongodb-native. Vous pouvez donc faire l'action en question par ceci:

User.collection.update({_id: user._id}, {$unset: {field: 1 }});

Depuis la version 2.0, vous pouvez faire:

User.update({_id: user._id}, {$unset: {field: 1 }}, callback);

Et depuis la version 2.4, si vous avez déjà une instance d'un modèle, vous pouvez faire:

doc.field = undefined;
doc.save(callback);
staackuser2
la source
Ce problème a été corrigé dans Mongoose 2.X, vous pouvez donc laisser la collection de côté.
staackuser2
4
Utilisez User.update({ _id: id }, { $unset: { field: 1 }}, callback)ou si vous avez une instance de document, définissez le chemin sur undefined, puis enregistrez-le:doc.field = undefined; doc.save()
aaronheckmann
25
Veuillez noter que si vous essayez de supprimer une ancienne propriété qui n'est plus définie dans votre schéma, vous devez le fairedoc.set('field', undefined)
evilcelery
3
qu'en est-il de la suppression doc.field.foo?
chovy
28
@evilcelery doc.set('field', undefined)peut ne pas suffire car le mode strict (par défaut) ne permet plus de définir des champs qui ne sont plus dans le schéma. doc.set('field', undefined, { strict: false })a bien fonctionné.
Alexander Link
56

Vous voudrez faire ceci:

User.findOne({}, function(err, user){
  user.key_to_delete = undefined;
  user.save();
});
deedubs
la source
3
Cela le mettra simplement à null - pas ce que l'OP demande.
Ian Henry
25
À partir de la version 2.4.0, définir une clé de document sur undefined passera le $ unset à mongodb aaronheckmann.posterous.com/mongoose-240
James Moore
30

J'utilise la mangouste et l'utilisation de l'une des fonctions ci-dessus m'a obligé. La fonction compile sans erreur mais le champ resterait toujours.

user.set('key_to_delete', undefined, {strict: false} );

a fait l'affaire pour moi.

Noushad
la source
Le vote pour cette réponse utile, dommage que @ alexander-link n'en ait pas fait une réponse en 2015 ( stackoverflow.com/questions/4486926/… )
w00t
1
Merci pour votre réponse, pour moi, les autres solutions ne fonctionnaient pas pour les objets imbriqués dans des tableaux!
BenSower
@BenSower C'était aussi mon cas. Seule cette solution a bien fonctionné car j'ai dû supprimer un champ avec un tableau après avoir trouvé l'ID d'un document spécifique
Luis Febro
Notez que la chaîne est un chemin vers la clé. Ainsi, si l'objet que vous souhaitez supprimer est imbriqué, vous devez y accéder. Cette réponse a résolu mon problème!
Bradyo le
8

À mongo syntax pour supprimer une clé, vous devez suivre:

{ $unset : { field : 1} }

Semble à Mongoose la même chose.

Éditer

Vérifiez cet exemple.

Andrew Orsich
la source
Pouvez-vous clarifier cette réponse et donner un exemple de code qui se rapporte à l'exemple de code ci-dessus?
Daniel Beardsley
désolé mais je ne suis pas convaincu de la mangouste. Au-dessus de la syntaxe, c'est la syntaxe mongo, donc je suppose que le pilote pour n'importe quel langage le prend en charge. J'ai trouvé un exemple, vérifiez-le dans ma réponse.
Andrew Orsich
1

Cela pourrait-il être un problème secondaire comme l'utilisation

function (user)

au lieu de

function(err, user)

pour le rappel de la trouvaille? J'essaie juste d'aider avec ça car j'avais déjà le cas.

Luc
la source
1

Le document Mongoose n'est PAS un objet javascript simple et c'est pourquoi vous ne pouvez pas utiliser l'opérateur de suppression. (Ou unset de la bibliothèque 'lodash').

Vos options sont de définir doc.path = null || undefined ou utiliser la méthode Document.toObject () pour transformer mangouste doc en objet simple et à partir de là, utilisez-la comme d'habitude. En savoir plus sur mongoose api-ref: http://mongoosejs.com/docs/api.html#document_Document-toObject

L'exemple ressemblerait à ceci:

User.findById(id, function(err, user) {
    if (err) return next(err);
    let userObject = user.toObject();
    // userObject is plain object
});
Petarr
la source
1

Essayer:

User.findOne({}, function(err, user){
  // user.key_to_delete = null; X
  `user.key_to_delete = undefined;`

  delete user.key_to_delete;

  user.save();
});
Jeisson Valderrama
la source
0

le problème avec toutes ces réponses est qu'elles fonctionnent pour un domaine. par exemple, disons que je veux supprimer tous les champs de mon document s'ils étaient une chaîne vide "". Tout d'abord, vous devez vérifier si le champ est une chaîne vide, mettez-le dans $unset:

function unsetEmptyFields(updateData) {
  const $unset = {};
  Object.keys(updatedData).forEach((key) => {
    if (!updatedData[key]) {
      $unset[key] = 1;
      delete updatedData[key];
    }
  });
  updatedData.$unset = $unset;

  if (isEmpty(updatedData.$unset)) { delete updatedData.$unset; }

  return updatedData;
}

function updateUserModel(data){
const updatedData = UnsetEmptyFiled(data);

    const Id = "";
    User.findOneAndUpdate(
      { _id: Id },
      updatedData, { new: true },
    );
}
Milad Ranjbar
la source
0

si vous souhaitez supprimer une clé de la collection, essayez cette méthode. cela a fonctionné pour moi

 db.getCollection('myDatabaseTestCollectionName').update({"FieldToDelete": {$exists: true}}, {$unset:{"FieldToDelete":1}}, false, true);
Bivin Vinod
la source
-4

vous pouvez utiliser delete user._doc.key

Joël Esperanza
la source