MongoDB聚合 - 按日期范围分组,其中一个文档可以属于多个范围

时间:2017-02-25 21:10:11

标签: mongodb mongodb-query aggregation-framework

我有下一个虚拟数据集:

[AdalSilentTokenAcquisitionException: Failed to acquire token silently. Call method AcquireToken]
   Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenSilentHandler.SendTokenRequestAsync() +98
   Microsoft.IdentityModel.Clients.ActiveDirectory.<RunAsync>d__0.MoveNext() +1807
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +13891908
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +61
   Microsoft.IdentityModel.Clients.ActiveDirectory.<AcquireTokenSilentCommonAsync>d__10.MoveNext() +317
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +13891908
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +61
   Microsoft.IdentityModel.Clients.ActiveDirectory.<AcquireTokenSilentAsync>d__5c.MoveNext() +268
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +13891908
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +61
   MRTWebApplication.<GetTokenForApplication>d__6.MoveNext() +539
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +13891908
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +61
   MRTWebApplication.<<GetUserData>b__5_0>d.MoveNext() +194
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +13891908
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +61
   Microsoft.Azure.ActiveDirectory.GraphClient.Extensions.<SetToken>d__1.MoveNext() +207
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +13891908
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +61
   Microsoft.Azure.ActiveDirectory.GraphClient.Extensions.<ExecuteAsync>d__4d`2.MoveNext() +986
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +13891908
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +61
   Microsoft.Azure.ActiveDirectory.GraphClient.Extensions.<<ExecuteAsync>b__0>d__2.MoveNext() +263

[AggregateException: One or more errors occurred.]
   System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) +4465776
   MRTWebApplication._Default.GetUserData() +778
   MRTWebApplication._Default.Page_Load(Object sender, EventArgs e) +43
   System.Web.UI.Control.OnLoad(EventArgs e) +109
   System.Web.UI.Control.LoadRecursive() +68
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +4498

我也有一些固定值{"id": 1, "date": "2017-04-01", "total": 1} {"id": 2, "date": "2017-04-03", "total": 2} {"id": 3, "date": "2017-04-10", "total": 1} {"id": 4, "date": "2017-04-11", "total": 1} 。让它等于5(count_of_days

我需要创建下一组:

count_of_days = 5

其中{"2017-04-01 + 5 days": count: 2, sum_of_total: 3} {"2017-04-03 + 5 days": count: 1, sum_of_total: 2} {"2017-04-10 + 5 days": count: 2, sum_of_total: 2} {"2017-04-11 + 5 days": count: 1, sum_of_total: 1} 是日期字段在count

范围内的文档数

所以对于[date; date + count_of_days]的文档,我们有这样的组

id=1

,因为

doc's 1 {"2017-04-01 + 5 days": count: 2, sum_of_total: 3} 的范围为date

doc's 2 [2017-04-01; 2017-04-06 (+ 5 days)] date的范围为2017-04-03

如何可以使用[2017-04-01; 2017-04-06 (+ 5 days)]aggregation framework执行此操作?

主要目标是生产力和计算速度

1 个答案:

答案 0 :(得分:0)

我不确定如何达到您要求的确切结果,但我能够根据固定的时间间隔而不是相对于记录的间隔对文档进行分组。

我假设你的文件是这样的:

{
    "_id" : ObjectId("58b36eb4b4af453e43480473"),
    "id" : 1.0,
    "date" : ISODate("2017-04-02T00:21:20.201Z"),
    "total" : 1.0
}

汇总查询:

// change this as you need, currently it is the number of milliseconds in 5 days
var interval = 1000 * 60 * 60 * 24 * 5; 

db.collection.aggregate([
    {
        $project: { 
            timestamp: { 
                $divide : [
                    { 
                        $subtract: [
                            {
                                $subtract: [ 
                                    '$date', 
                                    new Date("1970-01-01") 
                                ]
                            },
                            {
                                $mod: [
                                    {
                                        $subtract: [ 
                                            '$date', 
                                            new Date("1970-01-01") 
                                        ]
                                    },
                                    interval
                                ]
                            }
                       ] 
                    }, 
                    interval 
                ] 
            },

            date: 1,

            total: 1,

            id: 1
        }    
    },

    {
        $group: {
            _id: {
                timestamp: '$timestamp'
            },
            sum_of_total: { $sum: '$total' },
            count: { $sum: 1 }            
        }
    },

    {
        $project: {
            _id: 0,
            count: 1,
            sum_of_total: 1,
            rangeStart: { $add: [new Date(0), { $multiply: ['$_id.timestamp', interval] } ] }
        }
    },

    {
        $project: {
            _id: 0,
            count: 1,
            sum_of_total: 1,
            rangeStart: 1,
            rangeEnd: { $add: [ "$rangeStart", interval ] }
        }
    }
])