根据日期和其他字段汇总Mongo集合中的数据,并计算

时间:2015-12-02 20:52:42

标签: javascript node.js mongodb aggregation-framework

我保留了一系列事件,按日计算。如果事件发生一次,则它是'hit'(billState),这是每个位置和材料类。我很难将数据恢复到我需要的状态,我已经尝试了几个在SO上找到的例子,而且许多在Mongo Docs中...通常最终只得到我需要的部分内容。

我的收藏样本是这样的:

{
    "_id" : ObjectId("565ca8678e000995a09d1540"),
    "company" : "someCompany",
    "location" : "123",
    "materialCode" : "MATCODE",
    "materialClass" : "Class",
    "totalCount" : 8,
    "billState" : 1,
    "eventTime" : ISODate("2015-11-30T19:49:59.243Z")
}

{
    "_id" : ObjectId("565ca9778e000995a09d1541"),
    "company" : "someCompany",
    "location" : "1",
    "materialCode" : "WTHFA",
    "materialClass" : "OtherClass",
    "totalCount" : 16,
    "billState" : 1,
    "eventTime" : ISODate("2015-11-30T19:54:31.695Z")
}

{
    "_id" : ObjectId("565ca9778e000995a09d1541"),
    "company" : "someCompany",
    "location" : "12345",
    "materialCode" : "WTHFA",
    "materialClass" : "thirdClassOfMat",
    "totalCount" : 16,
    "billState" : 1,
    "eventTime" : ISODate("2015-11-30T19:54:31.695Z")
}

我可以有几个地点和materialClasses和我只是想计算“billState”是否为一(很容易因为它不会在集合中)。我需要按周,地点,日期,材料类分解它......就像这样......

    week1 mon tue wed thur fri sat sun
          ----------------------------
location 1  -  -   -  Class otherClass  = 2 
location 123-  -   -  Class otherClass  = 2 
    week2 mon tue wed thur fre sat sun
          ----------------------------
locations    material billState Count   = X
                                       -----
                                       month total

目前,我只能(另一方面)在另一个SO帖子上找到这个:

{
    "_id" : 12,
    "weeks" : {
        "week" : 48,
        "total" : 6,
        "days" : [ 
            {
                "day" : ISODate("2015-12-02T00:00:00.000Z"),
                "total" : 1
            }, 
            {
                "day" : ISODate("2015-12-01T00:00:00.000Z"),
                "total" : 1
            }, 
            {
                "day" : ISODate("2015-11-30T00:00:00.000Z"),
                "total" : 4
            }
        ]
    },
    "monthTotal" : 6
}

这就是我现在所拥有的......

myCollection.aggregate([

        // then total per day. Rounding dates
        { "$group": {
            "_id": {
                "$add": [
                    { "$subtract": [
                        { "$subtract": [ "$eventTime", new Date(0) ] },
                        { "$mod": [
                            { "$subtract": [ "$eventTime", new Date(0) ] },
                            1000 * 60 * 60 * 24
                        ]}                        
                    ]},
                    new Date(0)
                ]
            },
            "week": { "$first": { "$week": "$eventTime" } },
            "month": { "$first": { "$month": "$eventTime" } },
            "total": { "$sum": "$billState" }
        }},

        // Then group by week
        { "$group": {
            "_id": "$week",
            "month": { "$first": "$month" },
            "days": {
                "$push": {
                    "day": "$_id",
                    "total": "$total"
                }
            },
            "total": { "$sum": "$total" }
        }},

        // Then group by month
        { "$group": {
            "_id": "$month",
            "weeks": {
                "$push": {
                    "week": "$_id",
                    "total": "$total",
                    "days": "$days"
                }
            },
            "monthTotal": { "$sum": "$total" }
        }},

        {"$unwind": "$weeks"},

        { $out : "billingTotals" }
    ]);
};

我尝试过使用更多的$ groups,$ match和与$ project混淆,但似乎无法按日期将其分解,包括位置。真的,我只需要计算每天,地点和材料类别的事件,然后每周和每月的总和。因此,在任何一天,可能会在一个位置点击20个物质类别,在另一个位置点击“X”金额等等。每个级别每个位置每天只计算一次点击。

编辑: 输出示例(我认为这是一个好主意..,这是漫长的一天)

{
    "month" : 12 {
        "week" : 49 {
            "day" : 3 {
                "location": "123",
                "materials": [
                                {
                                    "class": "materialClass",
                                    "total" : 2
                                },

                                {
                                    "class": "otherMatClass",
                                    "total" : 5
                                }
                             ],
                "location": "1234",
                                "materials": [
                                {
                                    "class": "materialClass",
                                    "total" : 2
                                },

                                {
                                    "class": "otherMatClass",
                                    "total" : 5
                                }
                             ],

            },
            "day" : 4 {
                "location": "123",
                "materials": [
                                {
                                    "class": "materialClass",
                                    "total" : 2
                                },

                                {
                                    "class": "otherMatClass",
                                    "total" : 5
                                }
                             ]
            }

        },
        "week" : 50 {
            "day" : 3 {
                "location": "123",
                "materials": [
                                {
                                    "class": "materialClass",
                                    "total" : 2
                                },

                                {
                                    "class": "otherMatClass",
                                    "total" : 5
                                }
                             ]

            }
        }


    }
}

1 个答案:

答案 0 :(得分:0)

我已经有一段时间了,因为我在MongoDB中使用了聚合方法。我把它和你的模拟数据放在一起。不幸的是没有得到确切的结果;也许它仍然会有所帮助。祝好运。

db.materials.aggregate([
    {
      $match: {billState:{$ne:0}}
    },
    {
      $group: {
        _id:{location:"$location",date:{week:{$week:"$eventTime"},month:{$month:"$eventTime"},day:{$dayOfMonth:"$eventTime"},year:{$year:"$eventTime"}}},
        materials:{$addToSet:{code:"$materialCode",class:"$materialClass"}},
      }
    },
    {
      $sort:{"_id.date": 1}
    },
    {
      $group: {
        _id:{date:"$_id.date"},
        locations: {$addToSet:  {location:"$_id.location",materials:"$materials"}},
      }
    },
    {
      $project:{_id:0, date:"$_id.date",locations:1}
    }
]).pretty()

查询结果返回

{
    "locations" : [
        {
            "location" : "123",
            "materials" : [
                {
                    "code" : "MATCODE",
                    "class" : "Class"
                }
            ]
        },
        {
            "location" : "1",
            "materials" : [
                {
                    "code" : "WTHFA",
                    "class" : "OtherClass"
                }
            ]
        },
        {
            "location" : "12345",
            "materials" : [
                {
                    "code" : "WTHFA",
                    "class" : "thirdClassOfMat"
                },
                {
                    "code" : "WTHFC",
                    "class" : "thirdClassOfMatter"
                }
            ]
        }
    ],
    "date" : {
        "week" : 48,
        "month" : 11,
        "day" : 30,
        "year" : 2015
    }
}