如何在Mongoose中更新数组对象内指定元素的字段值?
Mongoose批量更新数组中所有匹配元素的问题
问题背景
我在Mongoose中定义了如下通知Schema:
var mongoose = require('mongoose'); var schema = mongoose.Schema; var notificationSchema = new schema({ createdOn:{type: Date, default: Date.now}, createdBy:{type: String, required:true}, sentTo:{type: Array, required:true}, content:{type:Object} }); module.exports = mongoose.model('notification',notificationSchema);
现有数据示例:
{ "_id" : ObjectId("6350dee274edf5586dc86099"), "sentTo" : [ { "username" : "user1", "status" : 0 }, { "username" : "user2", "status" : 0 }, { "username" : "user3", "status" : 0 }, { "username" : "user4", "status" : 0 } ], "status" : 0, "createdOn" : ISODate("2022-10-20T05:38:42.656Z"), "createdBy" : "system", "content" : { "text" : "This is content" } } { "_id" : ObjectId("6350dee274edf5586dc86099"), "sentTo" : [ { "username" : "user1", "status" : 0 }, { "username" : "user3", "status" : 0 } ], "status" : 0, "createdOn" : ISODate("2022-10-20T05:38:42.656Z"), "createdBy" : "system", "content" : { "text" : "This is another content" } }
需求:将所有通知中username为"user3"且status小于2的元素的status字段更新为1(status值说明:0=新通知,1=已查看,2=已读)。
当前使用的查询代码仅更新了数组中的第一个匹配元素:
let filters = {}; let updateObj = {}; filters['sentTo.username'] = "user3"; filters['sentTo.status'] = {$lt: 2} //only update whose status is less than 2 updateObj['sentTo.$.status'] = 1; Notification.updateMany(filters, updateObj, function (err, doc) { if(err){ console.log(err) } })
解决方案
原来的代码中使用$占位符只会匹配数组中第一个符合查询条件的元素,所以无法批量更新所有匹配项。要实现批量更新数组中所有符合条件的元素,需要使用Mongoose的arrayFilters配合占位符语法:
正确代码示例
Notification.updateMany( { 'sentTo.username': 'user3', 'sentTo.status': { $lt: 2 } }, { $set: { 'sentTo.$[elem].status': 1 } }, { arrayFilters: [ { 'elem.username': 'user3', 'elem.status': { $lt: 2 } } ] }, function(err, doc) { if (err) { console.log(err); } else { console.log('更新完成:', doc); } } );
代码说明
- 查询条件:筛选出包含
username为user3且status<2的sentTo数组的文档。 - 更新操作:使用
$set配合$[elem]占位符,该占位符会匹配arrayFilters中定义的所有符合条件的数组元素。 - arrayFilters:明确指定要更新的数组元素需满足
username为user3且status<2的条件,确保只更新目标元素。
这样就能批量更新所有符合条件的数组元素,而不仅仅是第一个匹配项。
内容的提问来源于stack exchange,提问作者kuldeep gupta
相关产品推荐
相关产品推荐

