【问题标题】:MongoDB Aggregation: How to add a nested field that is the sum of a double nested field?MongoDB聚合:如何添加一个嵌套字段,它是一个双重嵌套字段的总和?
【发布时间】:2023-03-05 12:58:01
【问题描述】:

我有多个以下结构的文档。

{
  "_id": ObjectId("60c07a1f9853c900c2026440"),
  "ProductID": "A",
  "Colours": [
    {
      "ID": "01",
      "Name": "BLACK",
      "Sizes": [
        {
          "Code": "S1",
          "Stock": 2
        },
        {
          "Code": "S2",
          "Stock": 3
        }
      ] 
    },
    {
      "ID": "02",
      "Name": "WHITE",
      "Sizes": [
        {
          "Code": "S1",
          "Stock": 5
        },
        {
          "Code": "S2",
          "Stock": 2
        }
      ] 
    }  
  ]
}  

我想检索文档,其中 Colours 的每个元素内都有一个名为 TotalStock 的附加字段,其中包含内部所有 SizesStock 的总和,同时省略 Sizes 本身。

所以我检索到的文档如下所示:

{
  "ProductID": "A",
  "Colours": [
    {
      "ID": "01",
      "Name": "BLACK",
      "TotalStock":5
    },
    {
      "ID": "02",
      "Name": "WHITE",
      "TotalStock":7
    }  
  ]
}  

通过$unwind$addFields$sum$project 的组合,我能够在一定程度上实现这一目标。这是我的查询:

db.collection.aggregate([
  {
    "$unwind": "$Colours"
  },
  {
    "$addFields": {
      "Colours.TotalStock": {
        "$sum": "$Colours.Sizes.Stock"
      }
    }
  },
  {
    "$project": {
      "_id": 0,
      "ProductID": 1,
      "Colours.ID": 1,
      "Colours.Name": 1,
      "Colours.TotalStock": 1,
    }
  }
])

问题

由于$unwind,我的查询为每种颜色提供了一个单独的文档,而我需要它们在同一个文档中。我仍在学习,不知道如何以及是否应该为此使用$group。我需要对查询进行哪些更改才能获得预期结果?

Here 是带有上述示例和查询的游乐场。

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    $unwind $group 等在集合级别工作,如果您需要的所有信息都在 1 个文档中,也会破坏您不需要它们的文档结构。 (但有时它们更易于使用)。

    相反,您可以使用 $map,$filter,$reduce 并在文档级别执行操作,而无需更改文档结构。

    db.collection.aggregate([
      {
        "$addFields": {
          "Colours": {
            "$map": {
              "input": "$Colours",
              "as": "color",
              "in": {
                "$mergeObjects": [
                  "$$color",
                  {
                    "TotalStock": {
                      "$reduce": {
                        "input": "$$color.Sizes",
                        "initialValue": 0,
                        "in": {
                          "$let": {
                            "vars": {
                              "total_stock": "$$value",
                              "csize": "$$this"
                            },
                            "in": {
                              "$add": [
                                "$$total_stock",
                                "$$csize.Stock"
                              ]
                            }
                          }
                        }
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      }
    ])
    

    Test code here

    查询不会更改文档,只会添加一个名为 $TotalStock 的额外字段

    【讨论】:

    • 相当整洁!学习使用$let$reduce$mergeObjects的完美示例。在$reduce 中,我看到我们可以只使用$add 而不使用$let,这样做是否有不利之处,或者您是否使用$let 以便更容易理解发生了什么?
    • 我认为你的意思是额外的$let$$value$$this 命名,我们不需要它,它只是帮助更容易理解代码的名称。MongoDB 目前分配缓慢使用$let 存储新变量的内存,因此如果性能很重要,请将其删除。我认为他们将来会修复它,
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    • 2016-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-21
    相关资源
    最近更新 更多