MongoDB:无需查询文档,依据文档内索引更新数组元素
无需先查询文档,直接用文档内字段更新MongoDB数组元素
文档结构示例
{ _id: ..., unique_id: 1234, config_no: 1, configs: [ { data: "qwertyuiop" // 随机字符串 }, { data: "asdfghjkl" // 随机字符串 } ] }
需求
要更新configs数组中,索引等于文档config_no字段值的元素的data属性,希望无需先查询文档直接完成更新,替代当前先查后更的两步操作。
当前实现(两步操作)
doc = db.collection.findOne({"unique_id": 1234}) config_no = doc.config_no db.collection.updateOne( {"unique_id": 1234}, {"$set": {"configs."+config_no+".data": "zxcvbnm"}} // 拼接成"configs.1.data" )
一步更新方案(MongoDB 4.2+)
利用MongoDB支持的聚合管道式更新,直接在更新操作中引用文档自身的字段值:
db.collection.updateOne( {"unique_id": 1234}, [ { $set: { "configs": { $map: { // 将数组元素与对应的索引配对 input: { $zip: { inputs: ["$configs", { $range: [0, { $size: "$configs" }] }] } }, as: "pair", in: { // 判断当前元素索引是否等于config_no $cond: [ { $eq: [{ $arrayElemAt: ["$$pair", 1] }, "$config_no"] }, // 匹配则更新data值 { data: "zxcvbnm" }, // 不匹配则保留原元素 { $arrayElemAt: ["$$pair", 0] } ] } } } } } ] )
方案说明
- 仅需一次
updateOne操作,无需提前查询文档获取config_no值 - 通过
$zip将configs数组与从0开始的索引序列配对,再用$map遍历每一对元素 - 用
$cond判断索引是否匹配config_no,匹配则替换data,否则保留原元素 - 如果
config_no的值超出数组索引范围(比如数组长度为2,config_no设为2),操作不会修改任何元素
内容的提问来源于stack exchange,提问作者odysseusmax
相关产品推荐
相关产品推荐

