mongodb - 重命名聚合结果中的数组子文档

标签 mongodb aggregation-framework

我正在使用 mongodb 3.4。运行我的聚合后,我的结果如下所示。我在两个集合之间进行了连接。

[   {
    "_id": { // rename _id to main
      "id": "ID_001",
      "name": "Fred flinstone Inc"
    },
    "types": [
      {
        "typeId": "TYPE1",
        "locations": [
          {
            "locationName": "Sydney", // rename locationName to name
            "units": [
              {
                "unitId": "PHG_BTG1" // remove the unitId, i just want the value
              }
            ]
          },
          {
            "locationName": "Brisbane",
            "units": [
              {
                "unitId": "PHG_KTN1"
              },
              {
                "unitId": "PHG_KTN2"
              }
            ]
          }
        ]
      }
    ]   } ]

我想将它投影为

[
  {
    "main": {
      "id": "ID_001",
      "name": "Fred flinstone Inc"
    },
    "types": [
      {
        "typeId": "TYPE1",
        "locations": [
          {
            "name": "Sydney",
            "units": [
              "PHG_BTG1"
            ]
          },
          {
            "name": "Brisbane",
            "units": [
              "PHG_KTN1",
              "PHG_KTN2"
            ]
          }
        ]
      }
    ]
  }
]

我该怎么做?我尝试了 $project 的各种组合但失败了。 示例

{ $project: {
  main: "$_id",
  "_id": 0,
  "types.locations.name": "$types.locations.locationName"
}}

将正确重命名 locations.name 但值显示 [Sydney, Brisbane] 的数组。当我尝试类似于 locations.units 的东西时也是如此。

我试图再次放松,但它会显示一个空的结果。非常感谢任何帮助。

最佳答案

$project alone 仅以您尝试使用它的形式真正做到“包容”或“排他”。因此,虽然您可以执行 "types": { "typeId": 1 } 以仅返回数组的那些项目,但实际上您不能仅仅通过“包含”或“排除”来更改底层结构。

此外,正如您发现的那样:

{ "$project": {
  "types.locations.units": "$types.locations.units.unitId"   
}}

结果与您的预期不同,因为 MongoDB 将每个值视为“映射的”数组元素:

"types" : [ 
    {
        "locations" : [ 
            {
                "units" : [ 
                    [ 
                        [ 
                            "PHG_BTG1"
                        ], 
                        [ 
                            "PHG_KTN1", 
                            "PHG_KTN2"
                        ]
                    ]
                ]
            }

或者更糟:

{ "$project": {
  "types.typeId": "$types.typeId"
}}

作为:

"types" : [ 
    {
        "typeId" : [ 
            "TYPE1"
        ]
    }
]

所以这里并不是真的需要“数组的数组”。这让我们明白为什么这实际上是使用您真正想要使用的以下运算符的“速记”。

要“转换”数组,您可以使用 $map :

{ "$project": {
  "_id": 0,
  "main": "$_id",
  "types": {
    "$map": {
      "input": "$types",
      "as": "t",
      "in": {
        "typeId": "$$t.typeId",
        "locations": {
          "$map": {
            "input": "$$t.locations",
            "as": "l",
            "in": {
              "name": "$$l.locationName",
              "units": {
                "$map": {
                  "input": "$$l.units",
                  "as": "u",
                  "in": "$$u.unitId"
                }
              }
            }
          }
        }
      }
    }
  }
}}

返回你想要的格式:

{
    "main" : {
        "id" : "ID_001",
        "name" : "Fred flinstone Inc"
    },
    "types" : [ 
        {
            "typeId" : "TYPE1",
            "locations" : [ 
                {
                    "name" : "Sydney",
                    "units" : [ 
                        "PHG_BTG1"
                    ]
                }, 
                {
                    "name" : "Brisbane",
                    "units" : [ 
                        "PHG_KTN1", 
                        "PHG_KTN2"
                    ]
                }
            ]
        }
    ]
}

本质上,每个“数组”都被“重新映射”为仅返回您实际指定的内部表示的结构。这就是你嵌套 $map 的原因其他内部$map表达式,处理每个数组元素的内部数组。

另请注意,由于我们实质上是在“重写”“type” 属性,因此 $project 中同名属性的默认行为通常是“复制”并保留顺序,“types” 实际上是现有文档结构的一部分,而 “main” 不是。因此,“类型” 将由标准投影包含“首先”表示。

“重写”意味着这被认为是一个新元素,因此键的顺序现在与投影中的顺序相同,即 “main”“type”之前",而不是相反。

关于mongodb - 重命名聚合结果中的数组子文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47090529/

相关文章:

mongodb - $在 mongodb 中查找多个级别

Mongodb 将聚合组值作为键

MongoDB - 查找匹配未知字段键的特定条件的文档

c# - MongoDB 驱动程序 2.2 的动态类型 - 如何不序列化 _t 类型鉴别器?

mysql - sql子查询到mongodb

json - npm unexpected token/in config.json at position 98

python - 选择要从 $lookup 返回的字段

MongoDB $从带过滤器的数组中拉出

mongodb - 使用官方mongodb golang包调试查询(命令监控)

MongoDb 访问具有特定属性的对象数组