MongoDB如何批量替换嵌套数组中resolutions.file_url的旧域名
替换MongoDB嵌套数组中的域名字段
问题背景
数据结构如下:
{ _id: ..., videos: [ { "url" : "<some url>", "converted" : true, // 其他字段 "resolutions": [ { "file_url": "<some_url>", "details": {...} }, { "file_url": "<some_url>", "details": {...} } ] }, // 更多video项 ] }
需要将所有videos.resolutions.file_url中的旧域名old_url.com/替换为新域名new_url.com/,且仅处理videos.converted: true的视频项。
原更新语句无法实现动态字符串替换,因为普通$set操作不能直接基于现有字段值做修改,需使用聚合管道式更新(MongoDB 4.2及以上版本支持)。
解决方案
使用聚合管道结合$map、$mergeObjects和$replaceOne操作符实现批量替换:
var oldUrl = "old_url.com/"; var newUrl = "new_url.com/"; db.getCollection('projects').updateMany( // 查询条件:匹配包含旧域名的项,且存在converted为true的视频 { "videos.resolutions.file_url": {$regex: oldUrl}, "videos.converted": true }, // 聚合管道更新逻辑 [ { $set: { videos: { $map: { input: "$videos", as: "video", in: { // 保留视频原有字段,仅更新resolutions $mergeObjects: [ "$$video", { resolutions: { // 仅处理converted为true的视频的resolutions $cond: [ "$$video.converted", { $map: { input: "$$video.resolutions", as: "res", in: { // 保留分辨率项原有字段,替换file_url $mergeObjects: [ "$$res", { file_url: { $replaceOne: { input: "$$res.file_url", find: oldUrl, replacement: newUrl } } } ] } } }, "$$video.resolutions" ] } } ] } } } } } ], // 更新所有匹配的文档 { multi: true } )
关键说明
updateMany:确保更新所有符合查询条件的文档,替代原update的multi: true配置- 聚合管道更新:允许使用聚合操作符动态修改字段值,这是实现基于原值替换的核心
$map遍历数组:分别遍历外层videos数组和内层resolutions数组,逐个处理元素$mergeObjects保留原有字段:避免覆盖视频或分辨率项中的其他字段(如url、details)$cond条件判断:仅对converted: true的视频项执行域名替换,符合需求范围$replaceOne字符串替换:精准替换file_url中的旧域名,若需要替换所有匹配项(而非第一个),可改用$replaceAll
内容的提问来源于stack exchange,提问作者Denys Siebov
相关产品推荐
相关产品推荐

