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

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

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


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.


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.


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.


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

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

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

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.