根据日期和其他字段聚合Mongo集合中的数据,并进行计数

Aggregate data from Mongo collection based on dates and other fields, and count

本文关键字:数据 集合 日期 其他 字段 Mongo      更新时间:2023-09-26

我保存了一个事件集合,按天计数。如果事件发生一次,则为"命中"(billState),这是按位置和材料类别进行的。我很难取回我需要的数据,我已经尝试了SO中的几个例子,以及Mongo文档中的许多例子。。通常只得到我需要得到的部分。

我收藏的样品是这样的:

{
    "_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
                                }
                             ]
            }
        }

    }
}

我在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
    }
}