基于unix时间戳的Mongodb按日聚合
我在谷歌上搜索了很多,但没有找到任何有用的解决方案。。。我想找到每日用户的总数。 我有一个名为session\u log的集合,其中包含如下文档基于unix时间戳的Mongodb按日聚合,mongodb,nosql,Mongodb,Nosql,我在谷歌上搜索了很多,但没有找到任何有用的解决方案。。。我想找到每日用户的总数。 我有一个名为session\u log的集合,其中包含如下文档 { "_id" : ObjectId("52c690955d3cdd831504ce30"), "SORTID" : NumberLong(1388744853), "PLAYERID" : 3, "LASTLOGIN" : NumberLong(1388744461), "ISLOGIN" : 1, "
{
"_id" : ObjectId("52c690955d3cdd831504ce30"),
"SORTID" : NumberLong(1388744853),
"PLAYERID" : 3,
"LASTLOGIN" : NumberLong(1388744461),
"ISLOGIN" : 1,
"LOGOUT" : NumberLong(1388744853)
}
我想从上次登录中聚合
这是我的疑问:
db.session_log.aggregate(
{ $group : {
_id: {
LASTLOGIN : "$LASTLOGIN"
},
count: { $sum: 1 }
}}
);
但它是按每次登录时间聚合的,而不是按每天聚合的。任何帮助都将不胜感激MongoDB 4.0及更新版本
使用
db.session_log.aggregate([
{ "$group": {
"_id": {
"$dateToString": {
"format": "%Y-%m-%d",
"date": {
"$toDate": {
"$multiply": [1000, "$LASTLOGIN"]
}
}
}
},
"count": { "$sum": 1 }
} }
])
或
db.session_log.aggregate([
{ "$group": {
"_id": {
"$dateToString": {
"format": "%Y-%m-%d",
"date": {
"$convert": {
"input": {
"$multiply": [1000, "$LASTLOGIN"]
},
"to": "date"
}
}
}
},
"count": { "$sum": 1 }
} }
])
MongoDB>=3.0和<4.0:
您需要将
LASTLOGIN
字段乘以1000,将其转换为毫秒时间戳
{ "$multiply": [1000, "$LASTLOGIN"] }
,然后转换为日期
"$add": [
new Date(0),
{ "$multiply": [1000, "$LASTLOGIN"] }
]
这可以在管道中完成,方法是将毫秒时间添加到零毫秒日期(0)
对象中,然后从转换的日期中提取,部分,然后在管道中使用这些部分按天对文档进行分组
因此,您应该将聚合管道更改为:
var project = {
"$project":{
"_id": 0,
"y": {
"$year": {
"$add": [
new Date(0),
{ "$multiply": [1000, "$LASTLOGIN"] }
]
}
},
"m": {
"$month": {
"$add": [
new Date(0),
{ "$multiply": [1000, "$LASTLOGIN"] }
]
}
},
"d": {
"$dayOfMonth": {
"$add": [
new Date(0),
{ "$multiply": [1000, "$LASTLOGIN"] }
]
}
}
}
},
group = {
"$group": {
"_id": {
"year": "$y",
"month": "$m",
"day": "$d"
},
"count" : { "$sum" : 1 }
}
};
运行聚合管道:
db.session_log.aggregate([ project, group ])
db.session_log.aggregate([ group ])
将给出以下结果(基于样本文档):
一个改进是在单个管道中运行上述内容
var group = {
"$group": {
"_id": {
"year": {
"$year": {
"$add": [
new Date(0),
{ "$multiply": [1000, "$LASTLOGIN"] }
]
}
},
"mmonth": {
"$month": {
"$add": [
new Date(0),
{ "$multiply": [1000, "$LASTLOGIN"] }
]
}
},
"day": {
"$dayOfMonth": {
"$add": [
new Date(0),
{ "$multiply": [1000, "$LASTLOGIN"] }
]
}
}
},
"count" : { "$sum" : 1 }
}
};
运行聚合管道:
db.session_log.aggregate([ project, group ])
db.session_log.aggregate([ group ])
首先,您的日期存储在
时间戳中,因此您需要首先通过添加新日期(0)
将时间戳
转换为ISODate
,然后将时间戳
乘以1000
得到ISODate
,如下:
{“$add”:[new Date(0),{“$multiply”:[1000,$LASTLOGIN]}]}
将时间戳转换为ISODate
现在使用,您需要使用将ISODate
转换为所需格式,然后按最终格式日期分组,这样聚合查询将:
db.session_log.aggregate({
$project: {
date: {
$concat: [{
$substr: [{
$year: {
"$add": [new Date(0), {
"$multiply": [1000, "$LASTLOGIN"]
}]
}
}, 0, 4]
}, "/", {
$substr: [{
$month: {
"$add": [new Date(0), {
"$multiply": [1000, "$LASTLOGIN"]
}]
}
}, 0, 4]
}, "/", {
$substr: [{
$dayOfMonth: {
"$add": [new Date(0), {
"$multiply": [1000, "$LASTLOGIN"]
}]
}
}, 0, 4]
}]
}
}
}, {
"$group": {
"_id": "$date",
"count": {
"$sum": 1
}
}
})
如果您将使用mongo版本3.0
及以上版本,则使用运算符将ISODate
转换为预定义格式,聚合查询为:
db.session_log.aggregate({
"$project": {
"ISODate": {
"$add": [new Date(0), {
"$multiply": [1000, "$LASTLOGIN"]
}]
}
}
}, {
"$project": {
"yearMonthDay": {
"$dateToString": {
"format": "%Y-%m-%d",
"date": "$ISODate"
}
}
}
}, {
"$group": {
"_id": "$yearMonthDay",
"count": {
"$sum": 1
}
}
})
你用的是哪个mongo版本?你能解释一下为什么我们需要这些数学练习来做一个简单的类型转换,让mongo使用日期,以及为什么我的解决方案不起作用吗?使用这个wave获取错误,比如“gmtime无法转换时间”@ ChristianDecheryMongoDB不允许从函数中插入管道变量/操作符,因为所有的内容都被解析为输入BSON,即在管道MangoDB进程BSON操作符到本机C++代码中,因此不允许JavaScript或其他任何东西。