MongoDB多个嵌套组

时间:2019-06-13 02:56:59

标签: mongodb mongodb-query aggregation-framework

我在mongodb中有这样的文档

{
  _id: "5cfed55974c7c52ecc33ada8",
  name: "Garona",
  realm: "Blackrock",
  faction: "Horde",
  race: "Orc",
  class: "Rogue",
  guild: "",
  level: 33,
  lastSeen: "2019-06-10T00:00:00.000Z",
  __v: 0
},
{
  _id: "5cfed55974c7c52ecc33ade8",
  name: "Muradin",
  realm: "Alleria",
  faction: "Alliance",
  race: "Dwarf",
  class: "Warrior",
  guild: "Stormstout Brewing Co",
  level: 42,
  lastSeen: "2019-06-11T00:00:00.000Z",
  __v: 0
}

我想做的是按字段分组并求和。到目前为止,我已经弄清楚了要像这样一次完成一个领域

{
  $group: {
    _id: {
      classes: '1',
      class: '$class'
    },
    total: { $sum: 1 }
  }
},
{
  $group: {
    _id: '$_id.classes',
    total: { $sum: '$total' },
    classes: {
      $push: {
        class: '$_id.class',
        total: '$total'
      }
    }
  }
}

会产生这样的东西

{
  _id: "1",
  total: 40,
  classes: [
    {
      class: "Warrior",
      total: 17
    },
    {
      class: "Rogue",
      total: 23
    }
}

但是我想一次在多个字段中执行此操作,这样我就可以获得这样的输出。

{
  _id: "1",
  total: 40,
  classes: [
    {
      class: "Warrior",
      total: 17
    },
    {
      class: "Rogue",
      total: 23
    },
  factions: [
    {
      faction: "Alliance",
      total: 27
    },
    {
      faction: "Horde",
      total: 13
    }
}

不,我想知道是否有可能以一种简单的方式在一个查询中执行此操作,或者是否对每个字段进行单独的查询会更好。

1 个答案:

答案 0 :(得分:2)

您可以使用$facet aggregation stage

  

在同一阶段的同一组输入文档上处理多个聚合管道。每个子管道在输出文档中都有其自己的字段,其结果存储为文档数组。

我只稍微修改了您的原始管道,然后将其复制到“派系”字段中。

我的解决方案中的最后3个阶段并不是必需的,它们只是清理了一点输出。

您可能可以从这里拿走,祝您好运。

db.collection.aggregate([
  {
    "$facet": {
      "classes": [
        {
          $group: {
            _id: "$class",
            total: {
              $sum: 1
            }
          }
        },
        {
          $group: {
            _id: null,
            total: {
              $sum: "$total"
            },
            "classes": {
              $push: {
                class: "$_id",
                total: "$total"
              }
            }
          }
        }
      ],
      "factions": [
        {
          $group: {
            _id: "$faction",
            total: {
              $sum: 1
            }
          }
        },
        {
          $group: {
            _id: null,
            total: {
              $sum: "$total"
            },
            "factions": {
              $push: {
                faction: "$_id",
                total: "$total"
              }
            }
          }
        }
      ]
    }
  },
  {
    $unwind: "$classes"
  },
  {
    $unwind: "$factions"
  },
  {
    $project: {
      "classes._id": 0,
      "factions._id": 0
    }
  }
])

输出

[
  {
    "classes": {
      "classes": [
        {
          "class": "Warrior",
          "total": 1
        },
        {
          "class": "Rogue",
          "total": 1
        }
      ],
      "total": 2
    },
    "factions": {
      "factions": [
        {
          "faction": "Alliance",
          "total": 1
        },
        {
          "faction": "Horde",
          "total": 1
        }
      ],
      "total": 2
    }
  }
]