我有一个MongoDB表DOCUMENTS,其中包含国家/地区、月份和交付合作伙伴名称列,
它们如下所示-

[{
        "id": "1",
        "month": "Jan",
        "deliveryPartner": {
            "name": "Lalamove"
        },
        "country": "ID"
    },
    {
        "id": "2",
        "month": "Jan",
        "deliveryPartner": {
            "name": "Lalamove"
        },
        "country": "ID"
    },
    {
        "id": "3",
        "month": "Jan",
        "deliveryPartner": {
            "name": "Borzo"
        },
        "country": "ID"
    },
    {
        "id": "4",
        "month": "Jan",
        "deliveryPartner": {
            "name": "Lalamove"
        },
        "country": "PH"
    },
    {
        "id": "5",
        "month": "Jan",
        "deliveryPartner": {
            "name": "Borzo"
        },
        "country": "PH"
    },
    {
        "id": "6",
        "month": "Feb",
        "deliveryPartner": {
            "name": "Borzo"
        },
        "country": "ID"
    },
    {
        "id": "7",
        "month": "Feb",
        "deliveryPartner": {
            "name": "Borzo"
        },
        "country": "ID"
    },
    {
        "id": "8",
        "month": "Feb",
        "deliveryPartner": {
            "name": "Lalamove"
        },
        "country": "PH"
    }
]

我想要编写一个聚合查询,它会给出如下所示的输出-

[
    {
        "deliveryPartner": "Lalamove",
        "country": "ID",
        "month": [
            {
                "Jan": 2
            },
            {
                "Feb": 0
            }
        ]
    },
    {
        "deliveryPartner": "Borzo",
        "country": "ID",
        "month": [
            {
                "Jan": 1
            },
            {
                "Feb": 2
            }
        ]
    },
    {
        "deliveryPartner": "Lalamove",
        "country": "PH",
        "month": [
            {
                "Jan": 1
            },
            {
                "Feb": 1
            }
        ]
    },
    {
        "deliveryPartner": "Borzo",
        "country": "PH",
        "month": [
            {
                "Jan": 1
            },
            {
                "Feb": 0
            }
        ]
    }
]

我try 了以下查询,但输出不是预期的结果-

let result = await con.aggregate([
    { $match : { year : "2023", "deliveryPartner.name": { $ne: null }, "country": { $ne: null }, "month": { $ne: null } } },
    {
      $group: {
        _id: {
          deliveryPartner: "$deliveryPartner.name",
          country: "$country",
          month: "$month"
        },
        count: { $sum: 1 }
      }
    },
    {
      $group: {
        _id: {
          deliveryPartner: "$_id.deliveryPartner",
          country: "$_id.country"
        },
        monthData: {
          $push: {
            month: "$_id.month",
            count: "$count"
          }
        }
      }
    }
  ]).toArray();

  console.log("result => ", JSON.stringify(result));

输出不会将缺少的月份计数设置为0

推荐答案

一种 Select 是使用$setWindowFields$reduce:

  1. 就像你做的那样$match$group.
  2. 添加月份索引以启用按月排序
  3. 使用$setWindowFields可将数据中所有月份的集合添加到每个文档中(并按monthIndex排序)
  4. $group,但现在按排序顺序推送
  5. 使用$set$reducemonthDataactualMonths合并
db.collection.aggregate([
  {$match: {
      "deliveryPartner.name": {$ne: null},
      "country": {$ne: null},
      "month": {$ne: null}
  }},
  {$group: {
      _id: {
        deliveryPartner: "$deliveryPartner.name",
        country: "$country",
        month: "$month"
      },
      count: {$sum: 1}
  }},
  {$addFields: {
      monthIndex: {$indexOfArray: [
          ["Jan", "Feb", "Mar", "Apr"], // add all months sorted
          "$_id.month"
      ]}
  }},
  {$setWindowFields: {
      sortBy: {monthIndex: 1},
      output: {actualMonths: {
          $addToSet: "$_id.month",
          window: {documents: ["unbounded", "unbounded"]}
      }}
  }},
  {$group: {
      _id: {
        deliveryPartner: "$_id.deliveryPartner",
        country: "$_id.country"
      },
      monthData: {$push: {month: "$_id.month", count: "$count"}},
      actualMonths: {$first: "$actualMonths"}
  }},
  {$set: {
      monthData: {
        $reduce: {
          input: "$actualMonths",
          initialValue: "$monthData",
          in: {$concatArrays: [
              "$$value",
              {$cond: [
                  {$in: ["$$this", "$monthData.month"]},
                  [],
                  [{count: 0, month: "$$this"}]
              ]}
          ]}
      }},
      actualMonths: "$$REMOVE"
  }}
])

看看它在playground example号公路上是如何工作的

Mongodb相关问答推荐

如何从MongoDB集合中获取第一个和最后一个元素?

在MongoDB查询中添加来自另一个集合的匹配文档的计数

当日期和时间在不同键的字符串中时,Mongo 查询过滤今天的数据

MongoDB - 将数组元素转换为新字段

可变用户 Select

在MongoDb的数组中计算大于某个数字的数字

MongoDB 支持的最 Big Data 库数

查找对象是否在预保存钩子mongoose中更改

为什么 local.oplog.rs 上每隔几分钟的活动就会锁定 mongo 客户端

.save() 不是函数 Mongoose

在mongo聚合中将ObjectID转换为字符串

Mongo:统计一组文档中单词出现的次数

Node.js 和 MongoDB,重用 DB 对象

Mongoose 和新架构:返回ReferenceError: Schema is not defined

错误:Could not connect to any servers in your MongoDB Atlas cluster

MongoDB - Permission denied for socket: /tmp/mongodb-27017.sock

MongoDB 按数组元素对文档进行排序

如何使用 mongoose 连接到 mongoDB Atlas

MongoDB Compass 中 JSON 输入意外结束

无法从 mongodb 中删除集合