Mongoose: findOneAndUpdate tidak mengembalikan dokumen yang diperbarui

257

Di bawah ini adalah kode saya

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

Saya sudah memiliki beberapa catatan dalam database mongo saya dan saya ingin menjalankan kode ini untuk memperbarui nama yang usianya 17 dan kemudian mencetak hasilnya di akhir kode.

Namun, mengapa saya masih mendapatkan hasil yang sama dari konsol (bukan nama yang dimodifikasi) tetapi ketika saya pergi ke mongo db command line dan ketik " db.cats.find();". Hasilnya datang dengan nama yang dimodifikasi.

Kemudian saya kembali menjalankan kode ini lagi dan hasilnya dimodifikasi.

Pertanyaan saya adalah: Jika data itu diubah, lalu mengapa saya masih mendapatkan data asli saat pertama kali console.log itu.

Mimpi
sumber

Jawaban:

527

Kenapa ini terjadi?

The standar adalah untuk mengembalikan asli, tidak berubah dokumen. Jika Anda ingin dokumen baru yang diperbarui dikembalikan, Anda harus memberikan argumen tambahan: objek dengan newproperti diatur ke true.

Dari dokumen luwak :

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

Pilihan yang tersedia

  • new: bool - jika benar , kembalikan dokumen yang dimodifikasi daripada yang asli. default menjadi false (diubah 4.0)

Larutan

Lulus {new: true}jika Anda ingin hasil yang diperbarui dalam docvariabel:

//                                                         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);
});
XCS
sumber
15
Ini tampaknya rusak bagi saya, masih mengembalikan dokumen lama dengan yang baru: true.
PDN
@ PDN Versi luwak / luwak apa yang kamu miliki? Itu mungkin mengacaukan cara kerjanya.
Cole Erickson
5
masuk akal bagi saya karena Anda sudah memiliki akses ke dokumen baru
danday74
3
itu berhasil untuk saya, saya menggunakan moogose versi 4.6.3, terima kasih
cesar Andavisa
2
NodeJs MongoDB Penggunaan asli -{ returnOriginal: false }
Nick Grealy
78

Bagi siapa pun yang menggunakan driver Node.js alih-alih Mongoose, Anda sebaiknya menggunakan {returnOriginal:false}bukan {new:true}.

Pedro Hoehl Carvalho
sumber
1
Terima kasih! Ini berfungsi untuk saya mongodb node versi 2.2.27
Kevin Ng
6
Ini semacam API idiot. Mengapa tidak menggunakan tanda tangan yang sama untuk Mongoose dengan API asli? Mengapa tidak mengembalikan dokumen yang diperbarui secara default? Luwak adalah salah satu libs yang lebih menjengkelkan yang saya gunakan setiap hari.
Askdesigners
56

Jadi, "findOneAndUpdate" memerlukan opsi untuk mengembalikan dokumen asli. Dan, opsinya adalah:

Shell MongoDB

{returnNewDocument: true}

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

Luwak

{new: true}

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

API Driver Node.js MongoDB:

{returnOriginal: false}

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

Tsuneo Yoshioka
sumber
Laravel:'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER
Giacomo Alzetta
39

Secara default findOneAndUpdate mengembalikan dokumen asli. Jika Anda ingin mengembalikan dokumen yang dimodifikasi, berikan objek opsi { new: true }ke fungsi:

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

});
hthserhs
sumber
2
mengapa _idnull?
chovy
14

Untuk siapa pun yang menemukan ini menggunakan gaya ES6 / ES7 dengan janji-janji asli, berikut adalah pola yang dapat Anda adopsi ...

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 */ }
Assaf Moldavsky
sumber
15
Mongoose akan mengembalikan janji jika Anda tidak memberikan fungsi panggilan balik. Tidak perlu membuat janji Anda sendiri!
joeytwiddle
1
@joeytwiddle Mongoose tidak akan mengembalikan Janji jika Anda tidak memberikan panggilan balik. Alih-alih mengembalikan objek Permintaan yang hanya menyediakan sebagian kecil dari API Janji. Ini sesuai dengan dokumentasi Mongoose.
Jamie Ridding
13

Ini adalah kode yang diperbarui untuk findOneAndUpdate. Berhasil.

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

Jika Anda ingin mengembalikan dokumen yang diubah, Anda perlu mengatur opsi {new:true}referensi API yang dapat Anda gunakanCat.findOneAndUpdate(conditions, update, options, callback) // executes

Diambil oleh Mongoose API resmi http://mongoosejs.com/docs/api.html#findoneandupdate_findOneAndUpdate Anda dapat menggunakan parameter berikut

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

Implementasi lain yang tidak diungkapkan dalam halaman API resmi dan yang saya lebih suka gunakan adalah Promiseimplementasi dasar yang memungkinkan Anda untuk memiliki di .catchmana Anda dapat menangani semua berbagai kesalahan Anda di sana.

    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);
    });
Jonathan Thurft
sumber
2

Di bawah ini menunjukkan permintaan untuk luwak findOneAndUpdate. Di sini new: truedigunakan untuk mendapatkan dokumen yang diperbarui dan fieldsdigunakan untuk bidang tertentu.

misalnya. 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();
Sourabh Khurana
sumber
1

Saya tahu, saya sudah terlambat tetapi izinkan saya menambahkan jawaban sederhana dan berfungsi di sini

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)
Aljohn Yamaro
sumber