【问题标题】:Mongodb aggregation (months) query set "missing fields" to zeroMongodb聚合(月)查询将“缺失字段”设置为零
【发布时间】:2021-03-18 11:59:23
【问题描述】:

我有一个聚合查询,它按月份对一年中的所有文档进行分组。

db.collection.aggregate([
  {
    $match: {
      dos: { $gte: startOfYear(new Date()), $lte: endOfYear(new Date()) },
     },
  },
  {
    $group: {
      _id: {
        $month: "$dos"
      },
      count: {
        $sum: 1
      }, 
    },
  },
  {
    $project: {
      month: "$_id",
      count: true,
      _id: false,
      
    },
  },
  {
    $sort: {
      month: 1,
      
    }, 
  },
])

结果为 3 个项目(1 月、2 月、3 月)。每个人都有一个在该月完成的文档。

[
  {
    "count": 1,
    "month": 1
  },
  {
    "count": 1,
    "month": 2
  },
  {
    "count": 1,
    "month": 3
  }
]

我想要的是添加缺少的字段,这些字段是 4 月到 12 月,带有 { count: 0 month: 4 }, { count: 0, month: 5 } 等等......

[
  {
    "count": 1,
    "month": 1
  },
  {
    "count": 1,
    "month": 2
  },
  {
    "count": 1,
    "month": 3
  },
  {
    "count": 0,
    "month": 4
  },
  {
    "count": 0,
    "month": 5
  },
  ...,
  { 
    "count": 0,
    "month": 12,
  }
]

这可能吗?

您可以在此处使用代码。 https://mongoplayground.net/p/ROjMQglxTjy

【问题讨论】:

  • 在聚合查询中没有直接的方法可以做到这一点,所以在查询结果之后。你可以用你的客户端语言来做。
  • 谢谢,我目前只是使用 for 循环为不存在的数据填充 0..

标签: mongodb mongodb-query


【解决方案1】:

这是可能的,因为输出的长度始终是固定的。所以想法是生成一个长度为 12 的数组,然后填充那些有数据的月份,否则为空计数。所以试试这个:

解决方案 #1

db.calendar.aggregate([
    // Put your match stage here.
    {
        $group: {
            _id: { $month: "$dos" },
            count: { $sum: 1 }
        },
    },
    {
        $group: {
            _id: null,
            array: { $push: "$$ROOT" }
        }
    },
    {
        $addFields: {
            array: {
                $map: {
                    input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
                    as: "month",
                    in: {
                        $cond: {
                            if: { $in: ["$$month", "$array._id"] },
                            then: {
                                $arrayElemAt: [
                                    "$array",
                                    { $indexOfArray: ["$array._id", "$$month"] }
                                ]
                            },
                            else: {
                                _id: "$$month",
                                count: 0
                            }
                        }
                    }
                }
            }
        }
    },
    { $unwind: "$array" },
    {
        $sort: { "array._id": 1 }
    },
    {
        $project: {
            _id: 0,
            count: "$array.count",
            month: "$array._id"
        }
    }
]);

解决方案 #2:与第一个相比效率更高。

db.calendar.aggregate([
    // Put your match stage here.
    {
        $group: {
            _id: { $month: "$dos" },
            count: { $sum: 1 }
        },
    },
    {
        $group: {
            _id: null,
            array: { $push: "$$ROOT" }
        }
    },
    {
        $addFields: {
            array: {
                $map: {
                    input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
                    as: "month",
                    in: {
                        $let: {
                            vars: {
                                index: { $indexOfArray: ["$array._id", "$$month"] }
                            },
                            in: {
                                $cond: [
                                    { $gt: ["$$index", -1] },
                                    { $arrayElemAt: ["$array", "$$index"] },
                                    { _id: "$$month", count: 0 }
                                ]
                            }
                        }
                    }
                }
            }
        }
    },
    { $unwind: "$array" },
    {
        $sort: { "array._id": 1 }
    },
    {
        $project: {
            _id: 0,
            count: "$array.count",
            month: "$array._id"
        }
    }
]);

输出:

/* 1 */
{
    "count" : 2,
    "month" : 1
},

/* 2 */
{
    "count" : 2,
    "month" : 2
},

/* 3 */
{
    "count" : 1,
    "month" : 3
},

/* 4 */
{
    "count" : 0,
    "month" : 4
},

/* 5 */
{
    "count" : 0,
    "month" : 5
},

/* 6 */
{
    "count" : 0,
    "month" : 6
},

/* 7 */
{
    "count" : 0,
    "month" : 7
},

/* 8 */
{
    "count" : 1,
    "month" : 8
},

/* 9 */
{
    "count" : 0,
    "month" : 9
},

/* 10 */
{
    "count" : 1,
    "month" : 10
},

/* 11 */
{
    "count" : 0,
    "month" : 11
},

/* 12 */
{
    "count" : 0,
    "month" : 12
}

测试数据:

/* 1 createdAt:3/17/2021, 7:27:28 PM*/
{
    "_id" : ObjectId("60520ac8479cd440a079c271"),
    "dos" : ISODate("2021-01-15T00:00:00.000+05:30")
},

/* 2 createdAt:3/17/2021, 7:27:28 PM*/
{
    "_id" : ObjectId("60520ac8479cd440a079c272"),
    "dos" : ISODate("2021-03-03T00:00:00.000+05:30")
},

/* 3 createdAt:3/17/2021, 7:27:28 PM*/
{
    "_id" : ObjectId("60520ac8479cd440a079c273"),
    "dos" : ISODate("2021-02-14T00:00:00.000+05:30")
},

/* 4 createdAt:3/17/2021, 7:27:28 PM*/
{
    "_id" : ObjectId("60520ac8479cd440a079c274"),
    "dos" : ISODate("2021-01-26T00:00:00.000+05:30")
},

/* 5 createdAt:3/17/2021, 7:27:28 PM*/
{
    "_id" : ObjectId("60520ac8479cd440a079c275"),
    "dos" : ISODate("2021-02-28T00:00:00.000+05:30")
},

/* 6 createdAt:3/17/2021, 7:27:28 PM*/
{
    "_id" : ObjectId("60520ac8479cd440a079c276"),
    "dos" : ISODate("2021-08-15T00:00:00.000+05:30")
},

/* 7 createdAt:3/17/2021, 7:27:28 PM*/
{
    "_id" : ObjectId("60520ac8479cd440a079c277"),
    "dos" : ISODate("2021-10-02T00:00:00.000+05:30")
}

【讨论】:

    猜你喜欢
    • 2021-02-16
    • 2022-01-14
    • 1970-01-01
    • 2019-06-18
    • 2021-10-09
    • 2015-10-09
    • 2020-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多