【问题标题】:MongoDB aggregation: Aggregate array into keyed objectsMongoDB聚合:将数组聚合成键控对象
【发布时间】:2018-08-24 03:57:03
【问题描述】:

我想使用聚合功能将文档数组扁平化为键控对象。这是我的文档示例:

[ 
    {
        "_id": 1,
        "texts": [
            { "language": "english", "text": "hello" },
            { "language": "german", "text": "hallo" },
            { "language": "french", "text": "bonjour" }
        ]
    }, …
]

预期结果:

[
     {
        "_id": 1,
        "texts": {
            "english": "hello",
            "german": "hallo",
            "french": "bonjour"
        }
    }, …
]

我研究过不同的运算符,例如$map,但这似乎集中在将数组转换为数组。我可能需要一个等效于 $reduce 的 JS,但找不到将我的值累积到对象中的方法。

有什么想法吗?

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    您需要 $map$arrayToObject 将 k-v 对数组转换为单个对象:

    db.col.aggregate([
        {
            $addFields: {
                texts: {
                    $arrayToObject: {
                        $map: {
                            input: "$texts",
                            as: "text",
                            in: {
                                k: "$$text.language",
                                v: "$$text.text"
                            }
                        }
                    }
                }
            }
        }
    ])
    

    【讨论】:

      【解决方案2】:

      您还可以将$zip$arrayToObject 一起使用。

      类似

      db.col.aggregate([{
        "$project": {
          "texts":{
           "$arrayToObject":{
             "$zip": {
              "inputs": [
                "$texts.language",
                "$texts.text"
              ]
            }
          }
        }}
      }])
      

      【讨论】:

      • 酷,更简洁。明天试一试,给反馈。谢谢!
      【解决方案3】:

      您可以在 mongodb 3.4.4 及更高版本中使用$map$arrayToObject 聚合来尝试此操作

      只需使用$maplanguage 字段与键(k) 转换为值(v) 并使用$arrayToObject 将数组转换为对象

      db.collection.aggregate([
        { "$addFields": {
          "texts": {
            "$map": {
              "input": "$texts",
              "in": {
                "k": "$$this.language",
                "v": "$$this.text"
              }
            }
          }
        }},
        { "$addFields": {
          "texts": { "$arrayToObject": "$texts" }
        }}
      ])
      

      【讨论】:

      • 非常感谢您的快速答复! +1 两者都是同时进行的,并且工作得同样好。我接受 mickl 的答案而不是你的答案的原因是,我更喜欢将所有内容都放在一个管道阶段。干杯!
      • 有趣的更新:我实际上仍在运行 MongoDB 3.4.6 -- 聚合仍然可以正常工作。
      • 不知道为什么...但是 $arrayToObject 已在 mongodb 3.6 中引入
      • 他们就是这样宣布的。请注意,这不是真的。 ;) 自 v3.4.4 以来一直存在:docs.mongodb.com/v3.4/reference/operator/aggregation/…
      • @dnickless 哎呀!!!我弄错了...感谢您对我的惩罚...更新了答案
      猜你喜欢
      • 2021-06-21
      • 1970-01-01
      • 1970-01-01
      • 2017-07-14
      • 2020-07-27
      • 1970-01-01
      • 2016-07-03
      • 2020-08-20
      • 2020-07-02
      相关资源
      最近更新 更多