Mungo: findOneAndUpdate gibt kein aktualisiertes Dokument zurück


256

Unten ist mein Code

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

Ich habe bereits einige Datensätze in meiner Mongo-Datenbank und möchte diesen Code ausführen, um den Namen für das Alter von 17 Jahren zu aktualisieren und das Ergebnis am Ende des Codes auszudrucken.

Warum erhalte ich jedoch immer noch das gleiche Ergebnis von der Konsole (nicht den geänderten Namen), sondern wenn ich zur Befehlszeile von mongo db gehe und " db.cats.find();" eingebe . Das Ergebnis kam mit geändertem Namen.

Dann gehe ich zurück, um diesen Code erneut auszuführen, und das Ergebnis wird geändert.

Meine Frage ist: Wenn die Daten geändert wurden, warum habe ich dann beim ersten Mal immer noch Originaldaten erhalten, als console.log es.

Antworten:


527

Warum passiert das?

Die Standardeinstellung ist die Rückkehr ursprüngliche, unveränderte Dokument. Wenn Sie möchten, dass das neue, aktualisierte Dokument zurückgegeben wird, müssen Sie ein zusätzliches Argument übergeben: ein Objekt mit der newEigenschaft set true.

Aus den Mungo-Dokumenten :

Abfrage # 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`
});

Verfügbare Optionen

  • new: bool - Wenn true , wird das geänderte Dokument anstelle des Originals zurückgegeben. Der Standardwert ist false (geändert in 4.0).

Lösung

Übergeben {new: true}Sie, wenn Sie das aktualisierte Ergebnis in der docVariablen wünschen :

//                                                         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
Dies scheint für mich kaputt zu sein, es gibt immer noch das alte Dokument mit new: true zurück.
PDN

@PDN Welche Version von Mungo / Mongo hast du? Das könnte die Funktionsweise beeinträchtigen.
Cole Erickson

5
macht für mich Sinn, da Sie bereits Zugriff auf das neue Dokument haben
danday74

3
es hat bei mir funktioniert, ich benutze moogose version 4.6.3, danke
cesar andavisa

2
NodeJs MongoDB Native verwendet -{ returnOriginal: false }
Nick Grealy

78

Für alle, die den Node.js-Treiber anstelle von Mongoose verwenden, sollten Sie {returnOriginal:false}stattdessen verwenden {new:true}.


1
Danke dir! Dies funktioniert für mich Mongodb Node Version 2.2.27
Kevin Ng

6
Dies ist eine Art Idioten-API. Warum nicht für Mongoose dieselben Signaturen verwenden wie für die native API? Warum nicht standardmäßig das aktualisierte Dokument zurückgeben? Mungo ist eine der irritierendsten Bibliotheken, die ich jeden Tag benutze.
Askdesigners

56

Für "findOneAndUpdate" ist daher eine Option zum Zurückgeben des Originaldokuments erforderlich. Und die Option ist:

MongoDB-Shell

{returnNewDocument: true}

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

Mungo

{new: true}

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

Node.js MongoDB-Treiber-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

Standardmäßig gibt findOneAndUpdate das Originaldokument zurück. Wenn Sie möchten, dass das geänderte Dokument zurückgegeben wird, übergeben Sie ein Optionsobjekt { new: true }an die Funktion:

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

});

2
Warum ist _idnull?
Chovy

14

Für alle, die im ES6 / ES7-Stil mit nativen Versprechungen darauf gestoßen sind, ist hier ein Muster, das Sie übernehmen können ...

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
Mungo gibt ein Versprechen zurück, wenn Sie keine Rückruffunktion bereitstellen. Sie müssen kein eigenes Versprechen erstellen!
Joeytwiddle

1
@joeytwiddle Mongoose gibt kein Versprechen zurück, wenn Sie keinen Rückruf bereitstellen. Stattdessen wird ein Abfrageobjekt zurückgegeben, das nur eine kleine Teilmenge der Promise-API bereitstellt. Dies ist gemäß der Mongoose-Dokumentation.
Jamie Ridding

13

Dies ist der aktualisierte Code für findOneAndUpdate. Es klappt.

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


3

Wenn Sie das geänderte Dokument zurückgeben möchten, müssen Sie die Option {new:true}API-Referenz festlegen, die Sie verwenden könnenCat.findOneAndUpdate(conditions, update, options, callback) // executes

Aufgenommen von der offiziellen Mongoose-API http://mongoosejs.com/docs/api.html#findoneandupdate_findOneAndUpdate Sie die folgenden Parameter verwenden

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

Eine andere Implementierung, die nicht auf der offiziellen API-Seite angegeben ist und die ich am liebsten verwende, ist die Basisimplementierung Promise, mit der .catchSie feststellen können, wo Sie mit all Ihren verschiedenen Fehlern umgehen können.

    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

Unten sehen Sie die Abfrage für Mungos findOneAndUpdate. Hier new: truewird das aktualisierte Dokument abgerufen und fieldsfür bestimmte Felder verwendet.

z.B. 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

Ich weiß, ich bin schon zu spät, aber lassen Sie mich hier meine einfache und funktionierende Antwort hinzufügen

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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.