Mongoose:findOneAndUpdate 不返回更新的文档

Posted

技术标签:

【中文标题】Mongoose:findOneAndUpdate 不返回更新的文档【英文标题】:Mongoose: findOneAndUpdate doesn't return updated document 【发布时间】:2019-04-10 09:11:02 【问题描述】:

下面是我的代码

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的时候还是得到了原始数据。

【问题讨论】:

使用new:true 似乎不适用于updateOne,将updateOne 替换为findOneAndUpdate 及其工作 【参考方案1】:

为什么会这样?

默认是返回原始的、未更改的文档。如果您希望返回新的、更新的文档,您必须传递一个附加参数:new 属性设置为 true 的对象。

来自mongoose docs:

查询#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 - 如果 true,则返回 修改后的 文档而不是原始文档。 默认为 false(在 4.0 中更改)

解决方案

如果您希望 doc 变量中的更新结果,请传递 new: true

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

【讨论】:

这对我来说似乎坏了,它仍然返回旧文档,新:true。 对我来说很有意义,因为您已经可以访问新文档 它对我有用,我使用的是 moogose 版本 4.6.3,谢谢 我得到了新文档,但 _id 为空,所以它不是真正的新文档。 NodeJs MongoDB 原生使用 - returnOriginal: false 【参考方案2】:

默认情况下findOneAndUpdate 返回原始文档。如果您希望它返回修改后的文档,请将选项对象 new: true 传递给函数:

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

);

【讨论】:

为什么_id 为空?【参考方案3】:

对于使用带有原生承诺的 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 */ 

【讨论】:

如果您不提供回调函数,Mongoose 将返回一个承诺。无需创建自己的承诺! 如果您不提供回调,@joeytwiddle Mongoose 不会返回 Promise。相反,它返回一个仅提供一小部分 Promise API 的 Query 对象。这是根据猫鼬文档。【参考方案4】:

对于使用 Node.js 驱动程序而不是 Mongoose 的任何人,您需要使用 returnOriginal:false 而不是 new:true

2021 - Mongodb ^4.2.0 更新 returnDocument: 'after'

【讨论】:

谢谢!这适用于我 mongodb 节点版本 2.2.27 这是一种愚蠢的 API。为什么不对 Mongoose 使用与原生 API 相同的签名?为什么不默认返回更新的文档? Mongoose 是我每天使用的比较烦人的库之一。 我正在使用 "mongodb": "^3.6.9" returnOriginal:false 已弃用。请改用 returnDocument: 'after' 谢谢!这对我有用。 @kunthet 我实际上正在使用它,因为文档解释说建议的 returnOriginal: false 已弃用。但由于某种原因,我无法让它发挥作用,而使用建议可以按预期工作。【参考方案5】:

这是findOneAndUpdate 的更新代码。它有效。

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

【讨论】:

【参考方案6】:

因此,“findOneAndUpdate”需要一个选项来返回原始文档。而且,选项是:

MongoDB 外壳

returnNewDocument: true

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

猫鼬

new: true

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

Node.js MongoDB 驱动 API:

returnOriginal: false

2021 - Mongodb ^4.2.0 更新 returnDocument: 'after'

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

【讨论】:

Laravel: 'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER【参考方案7】:

如果您想返回更改后的文档,您需要设置选项new:true API 参考您可以使用Cat.findOneAndUpdate(conditions, update, options, callback) // executes

由Mongoose官方APIhttp://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);
    );

【讨论】:

【参考方案8】:

下面显示了对 mongoose 的findOneAndUpdate 的查询。这里new: true用于获取更新的doc,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();

【讨论】:

【参考方案9】:

这里是 Mongoose 的维护者。您需要将new 选项设置为true(或者,等效地,将returnOriginal 设置为false

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

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

参见Mongoose findOneAndUpdate() docs 和this tutorial on updating documents in Mongoose。

【讨论】:

我误写了 returnNewDocument 而不是 new。感谢您的帮助! 如何在没有异步的情况下使用 await? 你不能@PeterXX 那只是一个代码sn-p。【参考方案10】:

我知道,我已经迟到了,但让我在这里添加我的简单有效答案

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)

【讨论】:

【参考方案11】:

在某些情况下,new: true 不起作用。 那你可以试试这个。

'returnNewDocument':true

【讨论】:

【参考方案12】:

2021 - Mongodb ^4.2.0 更新

这适用于 mongodb 节点驱动程序,NOT mongoose。

如果您使用“collection.findOneAndUpdate”进行搜索和更新,最新版本的 Mongodb 节点驱动程序似乎使用以下语法:

.findOneAndUpdate(query, update,  returnDocument: 'after' | 'before' )

搜索时自己在这里找不到答案,所以发布这个以防其他人处于同样的情况。

【讨论】:

这没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker。 - From Review

以上是关于Mongoose:findOneAndUpdate 不返回更新的文档的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose:findOneAndUpdate 不返回更新的文档

Mongoose - 使用 findOneAndUpdate 更新子文档

Mongoose `findOneAndUpdate` 回调不传递更新的文档

Mongoose `findOneAndUpdate` 回调不传递更新的文档

Mongoose:findOneAndUpdate 不适用于多种条件

Mongoose findOneAndUpdate 更新多个字段