updateMany() 后如何获取所有更新文档的值?

Posted

技术标签:

【中文标题】updateMany() 后如何获取所有更新文档的值?【英文标题】:How to get all updated documents' values after updateMany()? 【发布时间】:2019-12-20 23:41:22 【问题描述】:

期望的行为

更新多个文档中的属性值后,访问每个更新的文档的更新属性值。

(对于上下文,我正在增加多个用户的通知计数,然后将每个更新的值发送回各自的用户,如果他们已登录,则通过socket.io

我的尝试

let collection = mongo_client.db("users").collection("users"); 
let filter =  "user_email":  $in: users_to_notify  ;
let update =  $inc:  "new_notifications": 1  ;
let result = await collection.updateMany(filter, update);

// get the `new_notifications` value for all updated documents here

似乎没有适用于updateMany() 方法的returnOriginal 类型option

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

http://mongodb.github.io/node-mongodb-native/3.2/api/Collection.html#updateMany

这是可以理解的,因为returnOriginal 似乎只在更新一个文档时才有意义,例如在findOneAndUpdate() 方法的选项中。

问题

如果上述所有假设都成立,那么在 updateMany() 方法完成后,为所有更新的文档获取 new_notifications 值的最佳方法是什么?

是否只是进行另一个数据库调用以获取更新值的问题?


例如 - 这行得通:

let collection = mongo_client.db("users").collection("users"); 
let filter =  "user_email":  $in: users_to_notify  ;
let update =  $inc:  "new_notifications": 1  ;
await collection.updateMany(filter, update);

// make another database call to get updated values  
var options =  projection:  user_email: 1, username: 1, new_notifications: 1  ;
let docs = collection.find(filter, options).toArray(); 

/*expected result: 
[
    "user_email": "user_1@somedomain.com",
    "username": "user_1",
    "new_notifications": 17

,

    "user_email": "user_2@somedomain.com",
    "username": "user_2",
    "new_notifications": 5

]*/  

// create an object where each doc's user_email is a key with the value of new_notifications  
var new_notifications_object = ;

// iterate over docs and add each property and value  
for (let obj of docs) 
        new_notifications_object[obj.user_email] = obj.new_notifications; 


/*expected result: 

    "user_1@somedomain.com": 17,
    "user_2@somedomain.com": 3  
*/  

// iterare over logged_in_users
for (let key of Object.keys(logged_in_users)) 

    // get logged in user's email and socket id 
    let user_email = logged_in_users[key].user_email;
    let socket_id = key;

        // if the logged in user's email is in the users_to_notify array
        if (users_to_notify.indexOf(user_email) !== -1) 
            // emit to the socket's personal room  
            let notifications_count = new_notifications_object[user_email]; 
            io.to(socket_id).emit('new_notification',  "notifications_count": notifications_count );
        


【问题讨论】:

【参考方案1】:

updateMany() 不会返回更新的文档,但会返回一些计数。您必须运行另一个查询来获取这些更新。 建议您先执行 find(),然后在找到的项目的循环中执行 findByIdAndUpdate()。

let updatedRecord = [];
let result = await Model.find(query);
if (result.length > 0) 
  result.some(async e => 
    updatedRecord.push(await Model.findByIdAndUpdate(e._id, updateObj,  new: true ));
  );

return updatedRecord;

【讨论】:

以上是关于updateMany() 后如何获取所有更新文档的值?的主要内容,如果未能解决你的问题,请参考以下文章

返回未更新的搜索值列表(Mongoose、updateMany)

具有多个条件的 Mongoose updateMany() 返回 0

Mongodb:UpdateMany不更新嵌套数组数据

《MongoDB入门教程》第14篇 CRUD之更新文档

《MongoDB入门教程》第14篇 CRUD之更新文档

MongoDB基本操作-更新文档