更新Mongodb中嵌套数组内的对象

时间:2020-02-25 08:10:56

标签: node.js mongodb mongodb-query

我有一个看起来像这样的文档。我需要在嵌套数组中更新特定对象的地方。我需要使用名称编辑文本对象,该对象的区域设置 en

[
    {
        "_id": ObjectId("5e049ebc8e935c407f78c190"),
        "source": "homepage",
        "url": [
            {
                "type": "admindsg",
                "text": [
                    {
                        "locale": "en",
                        "name": "Admin DSG"
                    },
                    {
                        "locale": "nb",
                        "name": "Admin DSG"
                    },
                    {
                        "locale": "li",
                        "name": "Admin DSG"
                    },
                    {
                        "locale": "fi",
                        "name": "Admin DSG"
                    }
                ],
                "value": [
                    {
                        "locale": "en",
                        "link": "https://www.facebook.cloud"
                    },
                    {
                        "locale": "nb",
                        "link": "https://www.facebook.cloud"
                    },
                    {
                        "locale": "li",
                        "link": "https://www.facebook.cloud"
                    },
                    {
                        "locale": "fi",
                        "link": "https://www.facebook.cloud"
                    }
                ],
                "datetime": "2020-02-08 13:36:37"
            },
            {
                "type": "dataauth",
                "text": [
                    {
                        "locale": "en",
                        "name": "Data Authorities"
                    },
                    {
                        "locale": "nb",
                        "name": "Data Authorities"
                    },
                    {
                        "locale": "li",
                        "name": "Data Authorities"
                    },
                    {
                        "locale": "fi",
                        "name": "Data Authorities"
                    }
                ],
                "value": [
                    {
                        "locale": "en",
                        "link": "https://www.facebook.cloud"
                    },
                    {
                        "locale": "nb",
                        "link": "https://www.facebook.cloud"
                    },
                    {
                        "locale": "li",
                        "link": "https://www.facebook.cloud"
                    },
                    {
                        "locale": "fi",
                        "link": "https://www.facebook.cloud"
                    }
                ],
                "datetime": "2020-02-08 13:36:38"
            },
            {
                "type": "blog",
                "text": [
                    {
                        "locale": "en",
                        "name": "facebook blog"
                    },
                    {
                        "locale": "nb",
                        "name": "facebook blog"
                    },
                    {
                        "locale": "li",
                        "name": "facebook blog"
                    },
                    {
                        "locale": "fi",
                        "name": "facebook blog"
                    }
                ],
                "value": [
                    {
                        "locale": "en",
                        "link": "https://www.facebook.no"
                    },
                    {
                        "locale": "nb",
                        "link": "https://www.facebook.no"
                    },
                    {
                        "locale": "li",
                        "link": "https://www.facebook.no"
                    },
                    {
                        "locale": "fi",
                        "link": "https://www.facebook.no"
                    }
                ],
                "datetime": "2020-02-08 13:36:39"
            },
            {
                "type": "guide",
                "text": [
                    {
                        "locale": "en",
                        "name": "Guidelines for you"
                    },
                    {
                        "locale": "nb",
                        "name": "Guidelines for you"
                    },
                    {
                        "locale": "li",
                        "name": "Guidelines for you"
                    },
                    {
                        "locale": "fi",
                        "name": "Guidelines for you"
                    }
                ],
                "value": [
                    {
                        "locale": "en",
                        "link": "https://my.instagram.as/"
                    },
                    {
                        "locale": "nb",
                        "link": "https://my.instagram.as/"
                    },
                    {
                        "locale": "li",
                        "link": "https://my.instagram.as/"
                    },
                    {
                        "locale": "fi",
                        "link": "https://my.instagram.as/"
                    }
                ],
                "datetime": "2020-02-08 13:36:41"
            }
        ]
    }
]

完成此任务的最佳方法是什么?

这是我尝试过的查询:

db.getCollection('general').update({
    "source": "homepage",
    "url.type": "admindsg"
}, {
    "$set": {
        "url.text.$[elem].name": "YOYO"
    }
}, {
    "arrayFilters": [{
        "elem.locale": {
            "$eq": "en"
        }
    }],
    "multi": true
})

这将引发错误:

在路径中找不到标识符“ elem”的数组过滤器 'url.text。$ [elem] .name'

enter image description here

2 个答案:

答案 0 :(得分:2)

url字段是一个数组,因此您需要使用以下语法:

db.getCollection('general').update({
    "source": "homepage"
}, {
        "$set": {
            "url.$[urlId].text.$[textId].name": "YOYO"
        }
    }, {
        "arrayFilters": [
            { "urlId.type": "admindsg" },
            { "textId.locale": "en" },

        ],
        "multi": true
    })

filtered positional operator $

答案 1 :(得分:0)

问题是您有2个数组过滤器

  • url.type = "admindsg"
  • url.text.local = "en"

您可以使用聚合管道。这将是一种解决方案:

db.getCollection('general').aggregate([
   { $match: { source: "homepage" } },
   { $unwind: "$url" },
   {
      $set: {
         "url.text": {
            $cond: {
               if: { $eq: ["$url.type", "admindsg"] },
               then: {
                  $reduce: {
                     input: "$url.text",
                     initialValue: [],
                     in: {
                        $concatArrays: [
                           "$$value",
                           [{
                              $cond: {
                                 if: { $eq: ["$$this.locale", "fi"] },
                                 then: {
                                    $mergeObjects: [
                                       { locale: "$$this.locale" },
                                       { name: "Järjestelmänvalvoja DSG" }
                                    ]
                                 },
                                 else: "$$this"
                              }
                           }]
                        ]
                     }
                  }
               },
               else: "$url.text"
            }
         }
      }
   },
   {
      $group: {
         _id: { _id: "$_id", source: "$source" },
         url: { $push: "$$ROOT.url" }
      }
   },
   { $replaceRoot: { newRoot: { $mergeObjects: ["$$ROOT", "$_id"] } } }
]).forEach(function (doc) {
   db.getCollection('general').updateOne(
      { _id: doc._id },
      { $set: { url: doc.url } }
   );
})

您也可以使用$reduce代替$map

  {
    $set: {
      "url.text": {
        $cond: {
          if: { $eq: ["$url.type", "admindsg"] },
          then: {
            $map: {
              input: "$url.text",
              in: {
                $cond: {
                  if: { $eq: [ "$$this.locale", "fi" ] },
                  then: {
                    $mergeObjects: [
                      { locale: "$$this.locale" },
                      { name: "Järjestelmänvalvoja DSG" }
                    ]
                  },
                  else: "$$this"
                }
              }
            }
          },
          else: "$url.text"
        }
      }
    }
  },