Mangosta: findOneAndUpdate no devuelve el documento actualizado


257

Abajo está mi código

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');

var Cat = mongoose.model('Cat', {
    name: String,
    age: {type: Number, default: 20},
    create: {type: Date, default: Date.now} 
});

Cat.findOneAndUpdate({age: 17}, {$set:{name:"Naomi"}},function(err, doc){
    if(err){
        console.log("Something wrong when updating data!");
    }

    console.log(doc);
});

Ya tengo algún registro en mi base de datos de mongo y me gustaría ejecutar este código para actualizar el nombre para el que tiene 17 años y luego imprimir el resultado al final del código.

Sin embargo, por qué sigo obteniendo el mismo resultado de la consola (no el nombre modificado) pero cuando voy a la línea de comando de mongo db y escribo " db.cats.find();". El resultado vino con nombre modificado.

Luego vuelvo a ejecutar este código nuevamente y el resultado se modifica.

Mi pregunta es: si se modificaron los datos, ¿por qué todavía tengo datos originales por primera vez cuando console.log?

Respuestas:


528

¿Por qué pasa esto?

El valor predeterminado es devolver el documento original sin modificaciones . Si desea que se devuelva el documento nuevo y actualizado, debe pasar un argumento adicional: un objeto con la newpropiedad establecida en true.

De los documentos de mangosta :

Consulta # findOneAndUpdate

Model.findOneAndUpdate(conditions, update, options, (error, doc) => {
  // error: any errors that occurred
  // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
});

Opciones Disponibles

  • new: bool: si es verdadero , devuelve el documento modificado en lugar del original. el valor predeterminado es falso (cambiado en 4.0)

Solución

Pase {new: true}si desea el resultado actualizado en la docvariable:

//                                                         V--- THIS WAS ADDED
Cat.findOneAndUpdate({age: 17}, {$set:{name:"Naomi"}}, {new: true}, (err, doc) => {
    if (err) {
        console.log("Something wrong when updating data!");
    }

    console.log(doc);
});

15
Esto parece estar roto para mí, todavía devuelve el documento antiguo con nuevo: verdadero.
PDN

@PDN ¿Qué versión de mangosta / mongo tienes? Eso podría estar jugando con cómo funciona.
Cole Erickson

55
tiene sentido para mí ya que ya tiene acceso al nuevo documento
danday74

3
funcionó para mí, estoy usando moogose versión 4.6.3, gracias
cesar andavisa

2
Usos nativos de NodeJs MongoDB -{ returnOriginal: false }
Nick Grealy

78

Para cualquiera que use el controlador Node.js en lugar de Mongoose, querrá usarlo en {returnOriginal:false}lugar de {new:true}.


1
¡Gracias! Esto funciona para mí nodo mongodb versión 2.2.27
Kevin Ng

66
Esta es una especie de API idiota. ¿Por qué no usar las mismas firmas para Mongoose que la API nativa? ¿Por qué no devolver el documento actualizado de forma predeterminada? La mangosta es una de las librerías más irritantes que uso todos los días.
Askdesigners

56

Entonces, "findOneAndUpdate" requiere una opción para devolver el documento original. Y, la opción es:

Shell MongoDB

{returnNewDocument: true}

Ref: https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/

Mangosta

{new: true}

Ref: http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate

Node.js MongoDB Driver API:

{returnOriginal: false}

Ref: http://mongodb.github.io/node-mongodb-native/3.0/api/Collection.html#findOneAndUpdate


Laravel:'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER
Giacomo Alzetta

39

Por defecto, findOneAndUpdate devuelve el documento original. Si desea que devuelva el documento modificado, pase un objeto de opciones { new: true }a la función:

Cat.findOneAndUpdate({ age: 17 }, { $set: { name: "Naomi" } }, { new: true }, function(err, doc) {

});

2
¿Por qué es _idnulo?
chovy

14

Para quien tropezó con esto usando el estilo ES6 / ES7 con promesas nativas, aquí hay un patrón que puede adoptar ...

const user = { id: 1, name: "Fart Face 3rd"};
const userUpdate = { name: "Pizza Face" };

try {
    user = await new Promise( ( resolve, reject ) => {
        User.update( { _id: user.id }, userUpdate, { upsert: true, new: true }, ( error, obj ) => {
            if( error ) {
                console.error( JSON.stringify( error ) );
                return reject( error );
            }

            resolve( obj );
        });
    })
} catch( error ) { /* set the world on fire */ }

15
Mongoose le devolverá una promesa si no proporciona una función de devolución de llamada. ¡No hay necesidad de crear tu propia promesa!
joeytwiddle

1
@joeytwiddle Mongoose no devolverá una Promesa si no proporciona una devolución de llamada. En cambio, devuelve un objeto Query que proporciona solo un pequeño subconjunto de la API Promise. Esto está de acuerdo con la documentación de Mongoose.
Jamie Ridding

13

Este es el código actualizado para findOneAndUpdate. Funciona.

db.collection.findOneAndUpdate(    
  { age: 17 },      
  { $set: { name: "Naomi" } },      
  {
     returnNewDocument: true
  }    
)

9

Mantenedor de mangosta aquí. Debe establecer la newopción en true(o, equivalentemente, returnOriginalen false)

await User.findOneAndUpdate(filter, update, { new: true });

// Equivalent
await User.findOneAndUpdate(filter, update, { returnOriginal: false });

Consulte los documentos de MongoosefindOneAndUpdate() y este tutorial sobre la actualización de documentos en Mongoose .


Me he equivocado al escribir returnNewDocument en lugar de solo new. ¡gracias por la ayuda!
user1111527

3

Si desea devolver el documento alterado, debe establecer la opción de {new:true}referencia de API que puede usarCat.findOneAndUpdate(conditions, update, options, callback) // executes

Tomado por la API oficial de Mongoose http://mongoosejs.com/docs/api.html#findoneandupdate_findOneAndUpdate puede usar los siguientes parámetros

A.findOneAndUpdate(conditions, update, options, callback) // executes
A.findOneAndUpdate(conditions, update, options)  // returns Query
A.findOneAndUpdate(conditions, update, callback) // executes
A.findOneAndUpdate(conditions, update)           // returns Query
A.findOneAndUpdate()                             // returns Query

Otra implementación que no está expresada en la página oficial de la API y es la que prefiero usar es la Promiseimplementación base que le permite tener .catchdónde puede lidiar con todos sus diversos errores allí.

    let cat: catInterface = {
        name: "Naomi"
    };

    Cat.findOneAndUpdate({age:17}, cat,{new: true}).then((data) =>{
        if(data === null){
            throw new Error('Cat Not Found');
        }
        res.json({ message: 'Cat updated!' })
        console.log("New cat data", data);
    }).catch( (error) => {
        /*
            Deal with all your errors here with your preferred error handle middleware / method
         */
        res.status(500).json({ message: 'Some Error!' })
        console.log(error);
    });

2

A continuación se muestra la consulta de mangostas findOneAndUpdate. Aquí new: truese utiliza para obtener el documento actualizado y fieldsse utiliza para obtener campos específicos.

p.ej. findOneAndUpdate(conditions, update, options, callback)

await User.findOneAndUpdate({
      "_id": data.id,
    }, { $set: { name: "Amar", designation: "Software Developer" } }, {
      new: true,
      fields: {
        'name': 1,
        'designation': 1
      }
    }).exec();

1

Lo sé, ya llego tarde, pero déjenme agregar mi respuesta simple y funcional aquí

const query = {} //your query here
const update = {} //your update in json here
const option = {new: true} //will return updated document

const user = await User.findOneAndUpdate(query , update, option)
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.