MongoDB如何更新数组内最大版本对应的字段
问题描述
需求:在数组过滤器中针对最大版本参数更新对应值。
原始文档
{ _id: '9839021321', forms: [ { formName: 'sample_form_name', version: [ { version: '1', expirationDate: '2025-01-30', status: 'Inactive' }, { version: '2', expirationDate: '2025-03-15', status: 'Inactive' }, { version: '3', expirationDate: '2025-06-23', status: 'Inactive' } ] } ] }
期望修改后的文档
{ _id: '9839021321', forms: [ { formName: 'sample_form_name', version: [ { version: '1', expirationDate: '2025-01-30', status: 'Inactive' }, { version: '2', expirationDate: '2025-03-15', status: 'Inactive' }, { version: '3', status: 'Active' } ] } ] }
已编写的update操作结构
db["flows"].updateMany( {"_id":"id_value"}, { "$unset": {"forms.$[f].version.$[v].expirationDate": "true"}, "$set": {"forms.$[f].version.$[v].status": "Active"} }, {"arrayFilters": [ {"f.formName":{"$eq":"form_name_value"}}, {"v.status": {"$eq": "Active"}}, {"v.version": { /* 需要只影响版本号最大的元素 */}}, ]});
问题:如何在arrayFilters中指定匹配最大的v.version?仅了解aggregate用于数据查询,不知道怎么在更新操作里实现。
解决方案
MongoDB的arrayFilters没法直接在更新语句里筛选出数组里的最大值元素,它只支持简单条件匹配,用不了聚合函数计算。要实现这个需求,得改用聚合管道式更新,靠聚合操作定位最大版本再完成修改:
db["flows"].updateMany( { "_id": "id_value" }, [ { $set: { forms: { $map: { input: "$forms", as: "f", in: { $cond: [ { $eq: ["$$f.formName", "form_name_value"] }, { ..."$$f", version: { $map: { input: "$$f.version", as: "v", in: { $cond: [ { $eq: ["$$v.version", { $max: "$$f.version.version" }] }, { version: "$$v.version", status: "Active" }, "$$v" ] } } } }, "$$f" ] } } } } } ] )
代码说明:
- 外层
$map遍历forms数组,找出匹配目标formName的表单; - 内层
$map遍历该表单下的version数组,用$max拿到当前表单里的最大版本号; - 通过
$cond判断当前版本是不是最大值:- 是的话,就把
status设为Active,同时自动去掉expirationDate(因为新对象里没这个字段); - 不是的话,就保留原版本的所有内容。
- 是的话,就把
要是你想显式用unset而不是靠省略字段来移除,可以把内层的$cond分支改成这样:
{ $mergeObjects: [ "$$v", { status: "Active", expirationDate: "$$REMOVE" } ] }
这样就能精准定位到每个目标表单里的最大版本,完成状态更新和过期日期的移除。
内容的提问来源于stack exchange,提问作者Felipe Vidal
相关产品推荐
相关产品推荐

