Eliminar una clave de un documento de MongoDB usando Mongoose

103

Estoy usando la biblioteca Mongoose para acceder a MongoDB con node.js

¿Existe alguna forma de eliminar una clave de un documento ? es decir, no solo establecer el valor en nulo, sino eliminarlo.

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
fuente
1
Pensé que lo había encontrado, pero después de algunas pruebas: probablemente no. Sin embargo, esto tiene una buena discusión sobre el tema. groups.google.com/group/mongoose-orm/browse_thread/thread/…
Stephen
LOL no importa, supongo que esta fue tu publicación!
Stephen

Respuestas:

168

En las primeras versiones, habría tenido que desplegar el controlador node-mongodb-native. Cada modelo tiene un objeto de colección que contiene todos los métodos que ofrece node-mongodb-native. Entonces puede hacer la acción en cuestión de esta manera:

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

Desde la versión 2.0 puedes hacer:

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

Y desde la versión 2.4, si ya tienes una instancia de un modelo puedes hacer:

doc.field = undefined;
doc.save(callback);
staackuser2
fuente
Esto se ha solucionado en Mongoose 2.X, por lo que puede dejar la colección fuera.
staackuser2
4
De cualquier uso User.update({ _id: id }, { $unset: { field: 1 }}, callback)o si tiene una instancia de documento, establecer la ruta a indefinido y guardarla:doc.field = undefined; doc.save()
aaronheckmann
25
Solo una nota de que si está tratando de eliminar una propiedad antigua que ya no está definida en su esquema, debe hacerlodoc.set('field', undefined)
evilcelery
3
¿qué pasa con la eliminación doc.field.foo?
chovy
28
@evilcelery doc.set('field', undefined)puede no ser suficiente ya que el modo estricto (predeterminado) no permite establecer campos que ya no están en el esquema. doc.set('field', undefined, { strict: false })funcionó bien.
Alexander Link
56

Querrás hacer esto:

User.findOne({}, function(err, user){
  user.key_to_delete = undefined;
  user.save();
});
deedubs
fuente
3
Eso solo lo establecerá en nulo, no lo que está pidiendo el OP.
Ian Henry
25
A partir de la versión 2.4.0, establecer una clave de documento en indefinido pasará $ unset a mongodb aaronheckmann.posterous.com/mongoose-240
James Moore
30

Yo uso mangosta y el uso de cualquiera de las funciones anteriores me hizo el requisito. La función compila sin errores, pero el campo aún permanecería.

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

hizo el truco para mí.

Noushad
fuente
Al votar a favor de esta útil respuesta, lástima que @ alexander-link no la convirtió en una respuesta en 2015 ( stackoverflow.com/questions/4486926/… )
w00t
1
Gracias por su respuesta, para mí, ¡las otras soluciones no funcionaron para objetos anidados en matrices!
BenSower
@BenSower Este también fue mi caso. Solo esta solución funcionó bien porque tuve que eliminar un campo con una matriz después de encontrar la identificación de un documento específico
Luis Febro
Tenga en cuenta que la cadena es una ruta a la clave. Por lo tanto, si el objeto que desea eliminar está anidado, debe acceder a él. ¡Esta respuesta resolvió mi problema!
Bradyo
8

En la sintaxis de mongo para eliminar alguna clave, debe hacer lo siguiente:

{ $unset : { field : 1} }

En Mongoose parece lo mismo.

Editar

Mira este ejemplo.

Andrew Orsich
fuente
¿Puede aclarar esta respuesta y dar un ejemplo de código que se relacione con el código de ejemplo anterior?
Daniel Beardsley
lo siento, pero no tengo experiencia en mangosta. La sintaxis anterior es la sintaxis mongo, así que supongo que el controlador para cualquier idioma lo admite. Encontré un ejemplo, compruébalo en mi respuesta.
Andrew Orsich
1

¿Podría ser esto un problema secundario como usar

function (user)

en vez de

function(err, user)

para la devolución de llamada del hallazgo? Solo trato de ayudar con esto, ya que ya tenía el caso.

Luc
fuente
1

El documento Mongoose NO es un objeto simple de JavaScript y es por eso que no puede usar el operador de eliminación (o unsetde la biblioteca 'lodash').

Sus opciones son establecer doc.path = null || undefined o usar el método Document.toObject () para convertir el documento de mangosta en un objeto simple y desde allí usarlo como de costumbre. Leer más en mongoose api-ref: http://mongoosejs.com/docs/api.html#document_Document-toObject

El ejemplo se vería así:

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

Tratar:

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
fuente
0

el problema con todas estas respuestas es que funcionan para un campo. por ejemplo, digamos que quiero eliminar todos los campos de mi documento si fueran una cadena vacía "". Primero debe verificar si el campo es una cadena vacía y ponerlo en $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
fuente
0

si desea eliminar una clave de la colección, pruebe este método. esto funcionó para mí

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

puede usar delete user._doc.key

Joel Esperanza
fuente