这是我的数据架构:
{
_id: ...,
videos: [
{
"url" : <some url>,
"converted" : true,
...
"resolutions": [
{
"file_url": <some_url>,
"details": {...}
},
{
"file_url": <some_url>,
"details": {...}
},
{
"file_url": <some_url>,
"details": {...}
}
},
{video_2},
{video_N}
]
}
]
}
每个元素都有一个
videos
数组以及一个 resolutions
嵌套数组。
我需要更新每个 resolutions.file_url
并用新域名替换旧域名。
所以我需要将“old_url.com/”替换为“new_url.com/”。
这是我为此所做的查询:
var oldUrl = "old_url.com/";
var newUrl = "new_url.com/";
db.getCollection('projects').update(
{
"videos.resolutions.file_url": {$regex: oldUrl},
"videos.converted": true
},
{
"$set": {
"videos.$[elem].resolutions.$.file_url": ????
}
},
{
"arrayFilters": [{"elem.resolutions.file_url": {$regex: oldUrl}}],
"multi": true
}
)
它可以很好地处理一些静态数据,我可以用“hello world”更新所有道具,但不确定如何根据当前的
videos.$[elem].resolutions.$.file_url
值使该字符串替换正确。
我认为这不能在简单的更新查询中完成,特别是如果您想替换字段中的子字符串。
与(更新)聚合查询一起使用,您需要:
$map
- 迭代 videos
数组。覆盖 resolutions
数组的匹配元素。
$map
- 迭代 resolutions
数组,如果值满足正则表达式 (file_url
),则通过替换匹配的子字符串($replaceOne
或 $replaceAll
)来更新文档的 $regexMatch
字段。否则,保持原始值。
db.getCollection('projects').update({
"videos.resolutions.file_url": {
$regex: oldUrl
},
"videos.converted": true
},
[
{
$set: {
videos: {
$map: {
input: "$videos",
as: "video",
in: {
$cond: {
if: {
$eq: [
"$video.converted",
true
]
},
then: {
$mergeObjects: [
"$$video",
{
resolutions: {
$map: {
input: "$$video.resolutions",
as: "resolution",
in: {
$cond: {
if: {
$regexMatch: {
input: "$$resolution.file_url",
regex: oldUrl
}
},
then: {
$mergeObjects: [
"$$resolution",
{
file_url: {
$replaceAll: {
input: "$$resolution.file_url",
find: oldUrl,
replacement: newUrl
}
}
}
]
},
else: "$$resolution"
}
}
}
}
}
]
},
else: "$$video"
}
}
}
}
}
}
])