MongoDB - 按不同字段聚合然后每天计数
MongoDB - Aggregate by distinct field then count per day
我有一个收集设备数据的 mongodb 数据库。
示例文档是
{
"_id" : ObjectId("5c125a185dea1b0252c5352"),
"time" : ISODate("2018-12-13T15:09:42.536Z"),
"mac" : "10:06:21:3e:0a:ff",
}
目标是每天计算唯一 mac 个值,从数据库中的第一个文档到数据库中的最后一个文档。
我一直在玩弄并得出结论,在聚合期间我需要有多个组和项目。
这是我尝试过的 - 不确定方向是否正确或完全搞砸了。
pipeline = [
{"$project": {
"_id": 1,
"mac": 1,
"day": {
"$dayOfMonth":"$time"
},
"month": {
"$month":"$time"
},
"year": {
"$year":"$time"
}
}
},
{
"$project": {
"_id": 1,
"mac": 1,
"time": {
"$concat": [{
"$substr":["$year", 0, 4]
},
"-", {
"$substr": ["$month", 0, 2]
},
"-",
{
"$substr":["$day", 0, 2]
}]
}
}
},
{
"$group": {
"_id": {
"time": "$time",
"mac": "$mac"
}
},
"$group": {
"_id": "$_id.time",
"count":{"$sum": 1},
}
}
]
data = list(collection.aggregate(pipeline, allowDiskUse=True))
现在的输出看起来没有进行任何聚合,
[{"_id": null, "count": 751050}]
我使用 Pymongo 作为驱动程序并使用 Mongodb 4.
理想情况下,它应该只显示日期和计数(例如 { "_id" : "2018-12-13", "count" : 2 }.
我希望得到一些反馈和建议。
提前致谢。
有一个名为“$dateToString”的运算符,可以解决您的大部分问题。
编辑:没仔细看问题,@Asya Kamsky,谢谢指出。这是新答案。
pipeline = [
{
"$group": {
"_id": {
"date": {
$dateToString: {
format: "%Y-%m-%d",
date: "$time"
}
},
"mac": "$mac"
}
}
},
{
"$group": {
"_id": "$_id.date",
"count": {
"$sum": 1
}
}
}
]
[
{
"$project": {
"_id": 1,
"mac": 1,
"time": { "$dateToString": { "format": "%Y-%m-%d", "date": "$time", "timezone": "Africa/Johannesburg"}}
},
},
{
"$group": {
"_id":{
"time": "$time",
"mac": "$mac",
}}},{
"$group": {
"_id": "$_id.time",
"count":{"$sum": 1}
}},
{"$sort": SON([("_id", -1)])}
]
做它应该做的。
谢谢。 :)
我更喜欢尽量减少阶段数,尤其是避免不必要的 $group 阶段。所以我会用下面的管道来做:
pipeline = [
{ '$group' : {
'_id': { '$dateToString': { 'format': "%Y-%m-%d", 'date': "$time" } },
'macs':{ '$addToSet': '$mac' }
} },
{$addFields:{ 'macs':{'$size':'$macs'}}}
]
我有一个收集设备数据的 mongodb 数据库。 示例文档是
{
"_id" : ObjectId("5c125a185dea1b0252c5352"),
"time" : ISODate("2018-12-13T15:09:42.536Z"),
"mac" : "10:06:21:3e:0a:ff",
}
目标是每天计算唯一 mac 个值,从数据库中的第一个文档到数据库中的最后一个文档。
我一直在玩弄并得出结论,在聚合期间我需要有多个组和项目。
这是我尝试过的 - 不确定方向是否正确或完全搞砸了。
pipeline = [
{"$project": {
"_id": 1,
"mac": 1,
"day": {
"$dayOfMonth":"$time"
},
"month": {
"$month":"$time"
},
"year": {
"$year":"$time"
}
}
},
{
"$project": {
"_id": 1,
"mac": 1,
"time": {
"$concat": [{
"$substr":["$year", 0, 4]
},
"-", {
"$substr": ["$month", 0, 2]
},
"-",
{
"$substr":["$day", 0, 2]
}]
}
}
},
{
"$group": {
"_id": {
"time": "$time",
"mac": "$mac"
}
},
"$group": {
"_id": "$_id.time",
"count":{"$sum": 1},
}
}
]
data = list(collection.aggregate(pipeline, allowDiskUse=True))
现在的输出看起来没有进行任何聚合,
[{"_id": null, "count": 751050}]
我使用 Pymongo 作为驱动程序并使用 Mongodb 4.
理想情况下,它应该只显示日期和计数(例如 { "_id" : "2018-12-13", "count" : 2 }.
我希望得到一些反馈和建议。 提前致谢。
有一个名为“$dateToString”的运算符,可以解决您的大部分问题。
编辑:没仔细看问题,@Asya Kamsky,谢谢指出。这是新答案。
pipeline = [
{
"$group": {
"_id": {
"date": {
$dateToString: {
format: "%Y-%m-%d",
date: "$time"
}
},
"mac": "$mac"
}
}
},
{
"$group": {
"_id": "$_id.date",
"count": {
"$sum": 1
}
}
}
]
[
{
"$project": {
"_id": 1,
"mac": 1,
"time": { "$dateToString": { "format": "%Y-%m-%d", "date": "$time", "timezone": "Africa/Johannesburg"}}
},
},
{
"$group": {
"_id":{
"time": "$time",
"mac": "$mac",
}}},{
"$group": {
"_id": "$_id.time",
"count":{"$sum": 1}
}},
{"$sort": SON([("_id", -1)])}
]
做它应该做的。 谢谢。 :)
我更喜欢尽量减少阶段数,尤其是避免不必要的 $group 阶段。所以我会用下面的管道来做:
pipeline = [
{ '$group' : {
'_id': { '$dateToString': { 'format': "%Y-%m-%d", 'date': "$time" } },
'macs':{ '$addToSet': '$mac' }
} },
{$addFields:{ 'macs':{'$size':'$macs'}}}
]