代码之家  ›  专栏  ›  技术社区  ›  Denys Siebov

使用Mongo查询中的子字符串更新嵌入的数组元素

  •  0
  • Denys Siebov  · 技术社区  · 1 年前

    这是我的数据架构:

    {
        _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}
             ]
                
           }
    
        ]
    }
    

    每个元素都有一组具有分辨率的视频。 我需要更新每个resolutions.file_url并用新域替换旧域。

    所以我需要 old_url.com/<path> 替换为 new_url.com/<path> .

    这是我提出的问题

    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 价值

    1 回复  |  直到 1 年前
        1
  •  1
  •   Yong Shun    1 年前

    我不认为这可以在简单的更新查询中完成,尤其是如果您想替换字段中的子字符串。

    使用(更新)聚合查询时,您需要:

    1. $map -迭代 videos 大堆覆盖的匹配元素 resolutions 大堆

    2. $map -迭代 决议 数组,并更新 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"
                }
              }
            }
          }
        }
      }
    ])
    

    Demo @ Mongo Playground