基于unix时间戳的Mongodb按日聚合

基于unix时间戳的Mongodb按日聚合,mongodb,nosql,Mongodb,Nosql,我在谷歌上搜索了很多,但没有找到任何有用的解决方案。。。我想找到每日用户的总数。 我有一个名为session\u log的集合,其中包含如下文档 { "_id" : ObjectId("52c690955d3cdd831504ce30"), "SORTID" : NumberLong(1388744853), "PLAYERID" : 3, "LASTLOGIN" : NumberLong(1388744461), "ISLOGIN" : 1, "

我在谷歌上搜索了很多,但没有找到任何有用的解决方案。。。我想找到每日用户的总数。 我有一个名为session\u log的集合,其中包含如下文档

{
    "_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或其他任何东西。