【问题标题】:mongodb aggregate by month+date and sort itmongodb 按月+日期聚合并排序
【发布时间】:2020-03-28 10:31:10
【问题描述】:

我创建了这个聚合操作来返回每个月的订单列表。也就是说,像这样:

month1: [orders],
month2: [orders],
...

但是,我希望它从最近一个月到最近一个月排序。您可以看到我的组是带有 catch 的串联月份+年份。如果我只是简单地做了月+年,那么排序就行不通了:

MYYYY
12020
22020
...
92020
102020

如您所见,当我们到达第 10 个月时,订单已中断。问题是每个月都添加10,所以我们最终得到了

MYYYY
112020
122020
...
192020
202020
212020
222020
102021

哪些订单有效,但在下一年,即 2021 年中断。

那么,我怎样才能按月+年排序,既可以排序,又可以在响应中精美地显示内容?容易解析的东西。

        r = await Order.aggregate([
            {
                $match: {
                    launchDate: { "$gte": new Date(req.query.minDate), "$lte": new Date(req.query.maxDate) },
                    withdrawer: { $regex: utils.diacriticSensitiveRegex(req.query.withdrawer), $options: 'i' },
                    deleted: false
                }
            },
            {
                $sort: {
                    launchDate: 1
                }
            },
            {
                $group: {
                    _id: {
                        $concat: [
                            {
                                $toString: {
                                    $year: "$launchDate"
                                }
                            },
                            {
                                $toString: {
                                    $add: [{ $month: "$launchDate" }, 10]
                                }
                            }
                        ]
                    },
                    withdraws: {
                        $push: "$$ROOT"
                    }

                }
            },
            {
                $sort: {
                    _id: -1
                }
            },
            {
                $addFields: {
                    dateRange: "$_id"
                }
            },
            {
                $skip: skip
            },
            {
                $limit: perPage
            }
        ]);

【问题讨论】:

  • 您以 MYYYY 格式将月份放在首位,但您似乎希望将年份作为主要排序。我希望您需要一种更符合 YYYYM 的格式。或者你的格式更适合展示?
  • 月份使用两位数,年份开头,即使用格式%Y-%m。另一种解决方案是:首先按日期值使用$sort: {launchDate:1},然后使用$group。当然,你不能在$group之后再对结果进行排序

标签: node.js mongodb mongoose


【解决方案1】:

在您的$group 中,您的_id 中可以有多个子元素。这可以让您将年份和月份作为两个独立的实体,然后您可以随意呈现。您的组和排序将是:

{
    $group: {
        _id: {
            year: {
                $year: "$launchDate"
            },
            month: {
                $month: "$launchDate"
            }
        },
        withdraws: {
            $push: "$$ROOT"
        }

    }
},
{
    $sort: {
        "_id.year": 1,
        "_id.month": 1
    }
},

在上面的示例中,我假设您希望按升序对主要年份和次要月份进行排序,例如您将获得 2019 年 1 月、2019 年 2 月、...、2020 年 1 月、2020 年 2 月、2020 年 3 月。

如果您想获得年份和月份的格式化版本,当然可以将其添加到$addFields 或作为$group 的一部分。例如:

{
    $addFields: {
        formatted: {
            $concat:[
                {$toString:"$_id.year"},
                {$cond: {if: {$lt: ["$_id.month", 10]}, then: "0", else: ""}},
                {$toString: "$_id.month"}
            ]
        }
    }
}

替代方案

使用$dateToString$group 下的_id (https://docs.mongodb.com/manual/reference/operator/aggregation/dateToString/) 中格式化您的日期。以下应该可以解决问题:

{ $dateToString: {
    date: "$launchDate",
    format: ""%Y%m"
} }

【讨论】:

  • 我不明白 $dateToString 有什么帮助。看起来它输出20201, 20202, 20203,... 我是不是正确的?如何正确排序?
  • %m 为您提供 0 填充月份,因此它将是 202001、202002、202003,这将对应于首先按年排序,然后按月排序。
猜你喜欢
  • 2018-04-25
  • 1970-01-01
  • 1970-01-01
  • 2021-07-16
  • 2016-02-01
  • 2013-11-25
  • 1970-01-01
  • 1970-01-01
  • 2016-07-26
相关资源
最近更新 更多