พังพอน: findOneAndUpdate จะไม่ส่งคืนเอกสารที่อัปเดต


257

ด้านล่างเป็นรหัสของฉัน

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

ฉันมีบันทึกอยู่ในฐานข้อมูล mongo ของฉันแล้วและฉันต้องการเรียกใช้รหัสนี้เพื่ออัปเดตชื่อที่อายุ 17 แล้วพิมพ์ผลออกมาในตอนท้ายของรหัส

อย่างไรก็ตามทำไมฉันยังได้รับผลลัพธ์เดียวกันจากคอนโซล (ไม่ใช่ชื่อที่แก้ไข) แต่เมื่อฉันไปที่บรรทัดคำสั่ง mongo db และพิมพ์ " db.cats.find();" ผลลัพธ์มาพร้อมกับชื่อที่แก้ไข

จากนั้นฉันกลับไปเรียกใช้รหัสนี้อีกครั้งและผลลัพธ์ถูกแก้ไข

คำถามของฉันคือ: หากข้อมูลถูกแก้ไขดังนั้นทำไมฉันยังได้รับข้อมูลต้นฉบับในครั้งแรกเมื่อ console.log

คำตอบ:


529

ทำไมสิ่งนี้เกิดขึ้น

เริ่มต้นคือการกลับเดิมไม่เปลี่ยนแปลงเอกสาร ถ้าคุณต้องการให้เอกสารใหม่การปรับปรุงจะถูกส่งกลับต้องผ่านอาร์กิวเมนต์เพิ่มเติม: วัตถุที่มีที่ตั้งค่าคุณสมบัติการnewtrue

จากพังพอนเอกสาร :

แบบสอบถาม # 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`
});

ตัวเลือกที่มี

  • new: bool - ถ้าเป็นจริงให้ส่งคืนเอกสารที่ถูกดัดแปลงมากกว่าเอกสารต้นฉบับ ค่าเริ่มต้นเป็นเท็จ (เปลี่ยนเป็น 4.0)

สารละลาย

ผ่าน{new: true}ถ้าคุณต้องการผลลัพธ์ที่อัพเดตในdocตัวแปร:

//                                                         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
สิ่งนี้ดูเหมือนจะหักสำหรับฉันมันยังคงส่งคืนเอกสารเก่าด้วยใหม่: จริง
PDN

@PDN คุณมี Mongoose / Mongo รุ่นใด? ที่อาจล้อเล่นกับวิธีการทำงาน
Cole Erickson

5
เหมาะสมกับฉันเนื่องจากคุณสามารถเข้าถึงเอกสารใหม่ได้แล้ว
danday74

3
มันใช้งานได้สำหรับฉันฉันใช้เวอร์ชั่น moogose 4.6.3 ขอบคุณ
cesar andavisa

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

78

สำหรับทุกคนที่ใช้โปรแกรมควบคุม Node.js แทนพังพอนคุณจะต้องการที่จะใช้แทน {returnOriginal:false}{new:true}


1
ขอบคุณ! สิ่งนี้ใช้ได้กับฉัน mongodb node version 2.2.27
Kevin Ng

6
นี่คือ API ชนิดที่งี่เง่า ทำไมไม่ใช้ลายเซ็นเดียวกันกับ Mongoose เป็น API ดั้งเดิม ทำไมไม่ส่งคืนเอกสารที่อัปเดตเป็นค่าเริ่มต้น พังพอนเป็นหนึ่งใน libs ที่น่ารำคาญกว่าที่ฉันใช้ทุกวัน
ออกแบบ Ask

56

ดังนั้น "findOneAndUpdate" จึงต้องมีตัวเลือกในการส่งคืนเอกสารต้นฉบับ และตัวเลือกคือ:

เปลือก MongoDB

{returnNewDocument: true}

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

พังพอน

{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

โดยค่าเริ่มต้นfindOneAndUpdateจะส่งคืนเอกสารต้นฉบับ หากคุณต้องการให้ส่งคืนเอกสารที่แก้ไขผ่านวัตถุตัวเลือก{ new: true }ไปยังฟังก์ชัน:

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

});

2
ทำไม_idว่าง
chovy

14

สำหรับใครก็ตามที่เจอสิ่งนี้ด้วยสไตล์ ES6 / ES7 พร้อมด้วยสัญญาพื้นเมืองนี่คือรูปแบบที่คุณสามารถนำมาใช้ ...

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
พังพอนจะคืนสัญญาถ้าคุณไม่มีฟังก์ชั่นโทรกลับ ไม่จำเป็นต้องสร้างสัญญาของคุณเอง!
joeytwiddle

1
@joeytwiddle Mongoose จะไม่คืนสัญญาหากคุณไม่ได้ให้การติดต่อกลับ แต่จะส่งคืนวัตถุ Query ที่ให้ชุดย่อยขนาดเล็กของ Promise API เท่านั้น นี่เป็นไปตามเอกสารพังพอน
Jamie Ridding

13

findOneAndUpdateนี่คือโค้ดที่ปรับปรุงแล้วสำหรับ มันได้ผล.

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

9

ผู้ดูแลพังพอนที่นี่ คุณต้องตั้งค่าnewตัวเลือกเป็นtrue(หรือเท่ากันreturnOriginalเป็นfalse)

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

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

ดูพังพอนfindOneAndUpdate()เอกสารและการกวดวิชานี้ในการปรับปรุงเอกสารในพังพอน


ฉันเข้าใจผิดที่จะเขียน returnNewDocument แทนที่จะเป็นของใหม่ ขอบคุณที่ช่วยเหลือ!
user1111527

3

หากคุณต้องการส่งคืนเอกสารที่ถูกเปลี่ยนแปลงคุณต้องตั้งค่าการ{new:true}อ้างอิง API ตัวเลือกที่คุณสามารถใช้ได้Cat.findOneAndUpdate(conditions, update, options, callback) // executes

ดำเนินการโดย Mongoose API อย่างเป็นทางการhttp://mongoosejs.com/docs/api.html#findoneandupdate_findOneAndUpdateคุณสามารถใช้พารามิเตอร์ต่อไปนี้

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

การใช้งานอื่นที่ไม่ได้แสดงในหน้า API อย่างเป็นทางการและเป็นสิ่งที่ฉันต้องการใช้คือการPromiseใช้งานพื้นฐานที่ช่วยให้คุณมี.catchที่ที่คุณสามารถจัดการกับข้อผิดพลาดต่างๆของคุณที่นั่น

    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

findOneAndUpdateด้านล่างนี้แสดงให้เห็นว่าการค้นหาสำหรับพังพอน ที่นี่new: trueใช้เพื่อรับเอกสารที่อัปเดตและfieldsใช้สำหรับฟิลด์เฉพาะเพื่อรับ

เช่น. 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

ฉันรู้ว่าฉันมาช้าแล้ว แต่ให้ฉันเพิ่มคำตอบที่ง่ายและใช้งานได้ที่นี่

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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.