Mongoose: findOneAndUpdate không trả lại tài liệu cập nhật


256

Dưới đây là mã của tôi

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

Tôi đã có một số bản ghi trong cơ sở dữ liệu mongo của mình và tôi muốn chạy mã này để cập nhật tên cho độ tuổi 17 và sau đó in kết quả ra ở cuối mã.

Tuy nhiên, tại sao tôi vẫn nhận được kết quả tương tự từ bàn điều khiển (không phải tên đã sửa đổi) nhưng khi tôi đi đến dòng lệnh mongo db và gõ " db.cats.find();". Kết quả đi kèm với tên sửa đổi.

Sau đó tôi quay lại để chạy mã này một lần nữa và kết quả được sửa đổi.

Câu hỏi của tôi là: Nếu dữ liệu đã được sửa đổi, thì tại sao tôi vẫn nhận được dữ liệu gốc lần đầu tiên khi console.log nó.

Câu trả lời:


527

Tại sao điều này xảy ra?

Các mặc định là để trả lại bản gốc, không thay đổi gì tài liệu. Nếu bạn muốn trả lại tài liệu mới, cập nhật, bạn phải chuyển một đối số bổ sung: một đối tượng có thuộc newtính được đặt thành true.

Từ các tài liệu cầy mangut :

Truy vấn # 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`
});

Tùy chọn có sẵn

  • new: bool - nếu đúng , trả lại tài liệu đã sửa đổi thay vì tài liệu gốc. mặc định thành false (đã thay đổi trong 4.0)

Giải pháp

Vượt qua {new: true}nếu bạn muốn kết quả được cập nhật trong docbiến:

//                                                         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
Điều này dường như bị phá vỡ đối với tôi, nó vẫn trả về tài liệu cũ với new: true.
PDN

@PDN Bạn có phiên bản nào của mongoose / mongo? Điều đó có thể gây rối với cách nó hoạt động.
Cole Erickson

5
có ý nghĩa với tôi vì bạn đã có quyền truy cập vào tài liệu mới
danday74

3
nó hoạt động với tôi, tôi đang sử dụng moogose phiên bản 4.6.3, cảm ơn
Caesar andavisa

2
NodeJs MongoDB Bản địa sử dụng -{ returnOriginal: false }
Nick Grealy

78

Đối với bất kỳ ai sử dụng trình điều khiển Node.js thay vì Mongoose, bạn sẽ muốn sử dụng {returnOriginal:false}thay vì {new:true}.


1
Cảm ơn bạn! Điều này hoạt động với tôi phiên bản nút mongodb 2.2.27
Kevin Ng

6
Đây là một loại API ngốc. Tại sao không sử dụng cùng chữ ký cho Mongoose như API gốc? Tại sao không trả lại tài liệu cập nhật theo mặc định? Mongoose là một trong những libs khó chịu hơn mà tôi sử dụng hàng ngày.
Người hỏi

56

Vì vậy, "findOneAndUpdate" yêu cầu một tùy chọn để trả về tài liệu gốc. Và, tùy chọn là:

Vỏ MongoDB

{returnNewDocument: true}

Tham chiếu: https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/

Mongoose

{new: true}

Tham chiếu: http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate

API trình điều khiển MongoDB của Node.js:

{returnOriginal: false}

Tham chiếu: http://mongodb.github.io/node-mongodb-native/3.0/api/Collection.html#findOneAndUpdate


Ấu trùng:'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER
Giacomo Alzetta

39

Theo mặc định, findOneAndUpdate trả về tài liệu gốc. Nếu bạn muốn nó trả về tài liệu đã sửa đổi, hãy chuyển một đối tượng tùy chọn { new: true }cho hàm:

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

});

2
tại sao là _idnull
chovy

14

Đối với bất kỳ ai tình cờ sử dụng kiểu ES6 / ES7 với lời hứa riêng, đây là mẫu bạn có thể áp dụng ...

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 sẽ trả lại lời hứa nếu bạn không cung cấp chức năng gọi lại. Không cần phải tạo lời hứa của riêng bạn!
joeytwiddle

1
@joeytwiddle Mongoose sẽ không trả lại Lời hứa nếu bạn không cung cấp cuộc gọi lại. Thay vào đó, nó trả về một đối tượng Truy vấn chỉ cung cấp một tập hợp con nhỏ của API Promise. Đây là theo tài liệu Mongoose.
Jamie Ridding

13

Đây là mã cập nhật cho findOneAndUpdate. Nó hoạt động.

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

9

Mongoose duy trì ở đây. Bạn cần đặt newtùy chọn thành true(hoặc, tương đương, returnOriginalthành false)

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

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

Xem tài liệu MongoosefindOneAndUpdate()hướng dẫn này về cập nhật tài liệu trong Mongoose .


Tôi đã nhầm khi viết returnNewDocument thay vì chỉ mới. cảm ơn vì sự giúp đỡ!
dùng1111527

3

Nếu bạn muốn trả về tài liệu đã thay đổi, bạn cần đặt {new:true}tham chiếu API tùy chọn bạn có thể sử dụngCat.findOneAndUpdate(conditions, update, options, callback) // executes

Được thực hiện bởi API Mongoose chính thức http://mongoosejs.com/docs/api.html#findoneandupdate_findOneAndUpdate, bạn có thể sử dụng các tham số sau

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

Một triển khai khác không được thể hiện trong trang API chính thức và đó là điều tôi thích sử dụng là Promisetriển khai cơ sở cho phép bạn có .catchnơi bạn có thể xử lý tất cả các lỗi khác nhau của mình ở đó.

    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

Dưới đây cho thấy các truy vấn cho cầy mangut findOneAndUpdate. Ở đây new: trueđược sử dụng để có được tài liệu cập nhật và fieldsđược sử dụng cho các trường cụ thể để có được.

ví dụ. 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

Tôi biết, tôi đã trễ nhưng hãy để tôi thêm câu trả lời đơn giản và hiệu quả vào đây

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.