按月和按年分组不起作用 mongodb

Posted

技术标签:

【中文标题】按月和按年分组不起作用 mongodb【英文标题】:Group by month and year is not working mongodb 【发布时间】:2018-08-29 10:21:27 【问题描述】:

这是查询,

db.getCollection('_ad.insight').aggregate([
    
        $match:
            date: 
                $lte: ISODate('2018-12-31'),
                $gte: ISODate('2017-01-01')
            
        
    ,
    
        $project:
            _id: 0,
            year: $year: "$date",
            month: $month: "$date",
            day: $dayOfMonth: "$date",
            date: 1,
            clicks: 1,
            reach: 1 
        
    ,
    
        $group:
            _id: 
                month: "$month",
                year: "$year"
            ,
            clicks: $sum: "$clicks",
            reach: $sum: "$reach",
            date: $addToSet: "$date"
        
    ,
    
        $project:
            _id: 0,
            month: "$_id.month",
            year: "$_id.year",
            clicks: 1,
            reach: 1,
            date: 1
        
    
]);

我得到的回应,

/* 1 */

    "clicks" : 1096,
    "reach" : 33288,
    "date" : [
        ISODate("2018-01-01T00:00:00.000+05:00"),
        ISODate("2017-12-31T00:00:00.000+05:00"),
        ISODate("2017-12-28T00:00:00.000+05:00"),
        ISODate("2017-12-26T00:00:00.000+05:00"),
        ISODate("2017-12-24T00:00:00.000+05:00"),
        ISODate("2017-12-23T00:00:00.000+05:00"),
        ISODate("2017-12-25T00:00:00.000+05:00"),
        ISODate("2017-12-29T00:00:00.000+05:00"),
        ISODate("2017-12-22T00:00:00.000+05:00"),
        ISODate("2017-12-21T00:00:00.000+05:00"),
        ISODate("2017-12-30T00:00:00.000+05:00"),
        ISODate("2017-12-20T00:00:00.000+05:00"),
        ISODate("2017-12-27T00:00:00.000+05:00")
    ],
    "month" : 12,
    "year" : 2017
,

/* 2 */

    "clicks" : 1629,
    "reach" : 98113,
    "date" : [
        ISODate("2018-01-05T00:00:00.000+05:00"),
        ISODate("2018-01-04T00:00:00.000+05:00"),
        ISODate("2018-01-03T00:00:00.000+05:00"),
        ISODate("2018-01-07T00:00:00.000+05:00"),
        ISODate("2018-01-08T00:00:00.000+05:00"),
        ISODate("2018-01-02T00:00:00.000+05:00"),
        ISODate("2018-01-06T00:00:00.000+05:00")
    ],
    "month" : 1,
    "year" : 2018

样本集合: 它是一个扁平结构,包含大约 400 个字段,但我只显示我在查询中使用的那些。


    "_id" : ObjectId("5akjbrd51f193455adtrf6fc"),
    "clicks" : 5,
    "reach" : 10 
    "date" : ISODate("2018-01-06T00:00:00.000+05:00"),
    "post_engagement" : 127,
    "post_reactions" : 1,
    "post_shares" : 0,
    "qualificationfailed" : 0,
    "qualificationfailed_conversion_value" : 0

期望的输出:

/* 1 */

    "clicks" : 1096,
    "reach" : 33288,
    "date" : [
        ISODate("2018-01-01T00:00:00.000+05:00"),//this shouldn't be here
        ISODate("2017-12-31T00:00:00.000+05:00"),
        ISODate("2017-12-28T00:00:00.000+05:00"),
        ISODate("2017-12-26T00:00:00.000+05:00"),
        ISODate("2017-12-24T00:00:00.000+05:00"),
        ISODate("2017-12-23T00:00:00.000+05:00"),
        ISODate("2017-12-25T00:00:00.000+05:00"),
        ISODate("2017-12-29T00:00:00.000+05:00"),
        ISODate("2017-12-22T00:00:00.000+05:00"),
        ISODate("2017-12-21T00:00:00.000+05:00"),
        ISODate("2017-12-30T00:00:00.000+05:00"),
        ISODate("2017-12-20T00:00:00.000+05:00"),
        ISODate("2017-12-27T00:00:00.000+05:00")
    ],
    "month" : 12,
    "year" : 2017
,

/* 2 */

    "clicks" : 1629,
    "reach" : 98113,
    "date" : [
        // ISODate("2018-01-01T00:00:00.000+05:00") this should be in this group
        ISODate("2018-01-05T00:00:00.000+05:00"),
        ISODate("2018-01-04T00:00:00.000+05:00"),
        ISODate("2018-01-03T00:00:00.000+05:00"),
        ISODate("2018-01-07T00:00:00.000+05:00"),
        ISODate("2018-01-08T00:00:00.000+05:00"),
        ISODate("2018-01-02T00:00:00.000+05:00"),
        ISODate("2018-01-06T00:00:00.000+05:00")
    ],
    "month" : 1,
    "year" : 2018

问题是, ISODate("2018-01-01T00:00:00.000+05:00") 正如您在输出文档 1 中看到的,在日期数组中,上述日期位于第一个索引上。 它显示了“月”:12 和“年”:2017,因为我按月和年分组。 所以我担心的是,ISODate("2018-01-01T00:00:00.000+05:00") 应该属于第 2 组,即 2 个输出文档,但它显示在第 1 组中。

我不知道我做错了什么,因为它是一个简单的管道。请帮忙!!

【问题讨论】:

您能否粘贴一个集合样本和所需的输出? 已添加。请立即检查! 你的 mongo 服务器版本是多少? 3.6能用吗? @Veeram:是的,使用 3.6 您可以使用 tz 来提供时区字符串。像 $year: date: '$date', timezone: "America/Chicago" 这样的东西。更改为使用您的时区标识符。 【参考方案1】:

请注意,ISODate("2018-01-01T00:00:00.000+05:00")UTC + 5。这意味着该条目在 UTC 时间的日期为 2017-12-31T19:00:00。

Mongo 正在根据 UTC 对日期进行分组。

您可能想查看这篇文章以处理不同的时区 How to aggregate by year-month-day on a different timezone

【讨论】:

【参考方案2】:

正如 Juanín 提到的,$year 默认使用 UTC 时间。您现在可以在将日期转换为字符串时提及时区。参考https://docs.mongodb.com/manual/reference/operator/aggregation/month/index.html

下面将为您完成这项工作。

db.getCollection('_ad.insight').aggregate([
    
        $match:
            date: 
                $lte: ISODate('2018-12-31T00:00:00.000+05:00'),
                $gte: ISODate('2017-01-01T00:00:00.000+05:00')
            
        
    ,
    
        $project:
            _id: 0,
            year: $year: date: "$date",timezone: "+0500",
            month: $month: date: "$date",timezone: "+0500",
            day: $dayOfMonth: date: "$date",timezone: "+0500",
            date: 1,
            clicks: 1,
            reach: 1 
        
    ,
    
        $group:
            _id: 
                month: "$month",
                year: "$year"
            ,
            clicks: $sum: "$clicks",
            reach: $sum: "$reach",
            date: $addToSet: "$date"
        
    ,
    
        $project:
            _id: 0,
            month: "$_id.month",
            year: "$_id.year",
            clicks: 1,
            reach: 1,
            date: 1
        
    
]);

【讨论】:

以上是关于按月和按年分组不起作用 mongodb的主要内容,如果未能解决你的问题,请参考以下文章

按年和按月创建表空间

按月和日过滤 django 日期时间字段的问题

PowerBI按年累积折线图不起作用

c# List<T> 按年分组,然后按月分组

如何简化 Laravel 查询以按年搜索日期并按月分组

socket.io 和按对象 id 过滤 mongodb