【问题标题】:MongoDB 4.0.12 update nested array with concatMongoDB 4.0.12 使用 concat 更新嵌套数组
【发布时间】:2020-07-31 07:35:44
【问题描述】:

Mongo DB 4.0

我想通过连接字段来更新文档数组的所有元素 我有以下文件:

{
  "id": 123455,
  "articles": [
    {
      "country": "DE",
      "articleNumber": "123456789"
    },
    {
      "country": "AT",
      "articleNumber": "987654321"
    }
  ]
}

我需要用一个新字段来扩展文章,该字段与其他字段连接

{
  "id": 123455,
  "articles": [
    {
      "country": "DE",
      "articleNumber": "123456789",
      "countryArticleNumber": "DE123456789"
    },
    {
      "country": "AT",
      "articleNumber": "987654321",
      "countryArticleNumber": "AT987654321"
    }
  ]
}

我尝试了几种在 Stackoverflow 中找到的解决方案,例如:

db.articleDocument.update (
  {_id: ObjectId('5f15414ff3812f4838391edd')},
  {
    $push:
      {'articles.countryArticleNumber': 'dasd'}
  }
  )

但即使我得到了一个简单的更新

MongoWriteException:无法在其中创建字段“countryArticleNumber” 元素{文章:[{

我也尝试使用 db.articleDocument.updateOne,$set 而不是 $push,位置运算符

我期待这样的事情应该可以工作

db.articleDocument.updateOne(
  {_id: ObjectId('5f15414ff3812f4838391edd')},
  {
    $set:
      {
        "articles.$.countryArticleNumber": {
          $concat: ["articles.$.country", "articles.$.articleNumber"]
        }
      }
  }
  )

但是

位置运算符没有从查询中找到所需的匹配项。

感谢高级

【问题讨论】:

  • 您需要使用Update with Aggregation。聚合使用$map 数组运算符。
  • @prasad_ 您指的是 4.4 版文档。不幸的是,我使用的是 MongoDB 4.0。
  • 我的意思是,MongoDB v4.2(聚合更新从 v4.2 开始可用)。您仍然可以使用 same 聚合管道,然后进行更新 - 这将是一个两步操作。
  • 现在还有$addToSet,(我相信也是4.2)可以与更新一起使用,如果它丢失,它将创建数组。 docs.mongodb.com/manual/reference/operator/update/addToSet
  • 这里有一个类似的帖子,有一个答案:Updating data type to an Object in mongoDB。请注意$map 的用法,您可以在其中使用两个现有字段创建countryArticleNumber

标签: mongodb


【解决方案1】:

对于 v4.0,可能是您必须执行两个查询的一种解决方案,

  • 使用aggregation$map$project$addFields
  • 使用updateOne()更新返回的聚合结果
db.articleDocument.aggregate([
  {
    $match: {
      _id: ObjectId("5f15414ff3812f4838391edd")
    }
  },
  {
    $project: {
      _id: 1,
      articles: {
        $map: {
          input: "$articles",
          as: "article",
          in: {
            country: "$$article.country",
            articleNumber: "$$article.articleNumber",
            countryArticleNumber: {
              $concat: [
                "$$article.country",
                "$$article.articleNumber"
              ]
            }
          }
        }
      }
    }
  }
])
.forEach(function(doc) { 
  db.articleDocument.updateOne( 
    { _id: doc._id }, 
    { $set: { articles: doc.articles } } 
  )
})

也可以使用$addFields 代替$project

聚合Working Playground


v4.2,新增功能update with aggregation pipeline

db.articleDocument.updateMany(
    {
        "_id" : ObjectId("5f15414ff3812f4838391edd")
    },
    [
        {
            $addFields: {
                articles: {
                    $map: {
                        input: "$articles",
                        as: "article",
                        in: {
                            country: "$$article.country",
                            articleNumber: "$$article.articleNumber",
                            countryArticleNumber: {
                                $concat: [
                                    "$$article.country",
                                    "$$article.articleNumber"
                                ]
                            }
                        }
                    }
                }
            }
        }
    ]
)

注意:确保 mongo shell 版本应 >= 4.2

【讨论】:

  • 我尝试了您提供的聚合函数来查看结果,但我得到:“无法识别的管道阶段名称:'$set'”在 MongoPlayground 中工作,但在 Mongo 4.0 上没有
  • 谢谢 - 现在聚合工作。但是我在 doc => 的每个地方都有一个 SyntaxError 有什么想法吗?
  • 我在 IntelliJ 数据库选项卡中执行此操作
  • thx - 聚合工作正常,但迭代不起作用。 java.lang.Exception: TypeError: Right-hand-side of instanceof is not an object TypeError: Right-hand-side of instanceof is not an object at Iterator.Iterator (all-standalone.js:79096:25) 也许这有与 Intellj 有关的事情
  • 我们将把我们的 MongoDB 更新到 4.2 - 我会再试一次,让你更新
猜你喜欢
  • 2018-10-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多