基于unix时间戳的Mongodb聚合

时间:2015-10-12 10:23:08

标签: mongodb nosql

我用google搜索了很多,但没有找到任何有用的解决方案......我想查找每日用户总数。 我有一个名为 session_log 的集合,其中包含以下文档

public void onValueChanged(ValueChangeEvent ev){
  BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
  DCIteratorBinding iterBind = (DCIteratorBinding)bindings.get("MpStavkeulazaView5Iterator");
  System.out.println("Vrijednost je" + ev.getNewValue());
  ev.processUpdates(FacesContext.getCurrentInstance());
  Row row = iterBind.getCurrentRow();
  System.out.println("Proizvod: " + row.getAttribute("Proizvod"));
  System.out.println("Jmjere: " + row.getAttribute("Jmjere"));
}

我想从LASTLOGIN聚合......

这是我的疑问:

{
    "_id" : ObjectId("52c690955d3cdd831504ce30"),
    "SORTID" : NumberLong(1388744853),
    "PLAYERID" : 3,
    "LASTLOGIN" : NumberLong(1388744461),
    "ISLOGIN" : 1,
    "LOGOUT" : NumberLong(1388744853)
}

但它是按每个登录时间聚合,而不是每天。任何帮助将不胜感激

2 个答案:

答案 0 :(得分:22)

MongoDB 4.0及更新版

使用 $toDate

db.session_log.aggregate([
    { "$group": {
        "_id": {
            "$dateToString": {
                "format": "%Y-%m-%d",
                "date": {
                    "$toDate": { 
                        "$multiply": [1000, "$LASTLOGIN"]
                    }
                }
            }
        },
        "count": { "$sum": 1 }
    } }
])

$convert

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:

db.session_log.aggregate([
    { "$group": {
        "_id": {
            "$dateToString": {
                "format": "%Y-%m-%d",
                "date": {
                    "$add": [
                        new Date(0), 
                        { "$multiply": [1000, "$LASTLOGIN"] }
                    ]
                }
            }
        },
        "count": { "$sum": 1 }
    } }
])

您需要将LASTLOGIN字段转换为毫秒时间戳,方法是将值乘以1000

{ "$multiply": [1000, "$LASTLOGIN"] }

,然后转换为日期

"$add": [
    new Date(0),
    { "$multiply": [1000, "$LASTLOGIN"] }
]

这可以在 $project 管道中完成,方法是将您的毫秒时间添加到零毫秒Date(0)对象,然后提取 $year $month $dayOfMonth 来自转换日期的部分,您可以在 $group中使用这些部分管道,以便在当天对文档进行分组。

因此,您应该将聚合管道更改为:

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 ])

将给出以下结果(基于样本文档):

{ "_id" : { "year" : 2014, "month" : 1, "day" : 3 }, "count" : 1 }

改进将是在单个管道中运行上述

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([ group ])

答案 1 :(得分:1)

首先,您的日期存储在timestamp中,因此您需要先使用timestampISODate转换为new Date(0),然后将timestamp乘以{{ 1}}然后你会得到这样的1000

ISODate这会将时间戳转换为ISODate。

现在使用date aggregation,您需要使用$concat以所需格式转换{"$add":[new Date(0),{"$multiply":[1000,"$LASTLOGIN"]}]},然后按最终格式化日期分组,以便汇总查询:

ISODate

如果您使用mongo版本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 } } }) 及更高版本,请使用dateToString运算符将3.0转换为预定义格式,汇总查询为:

ISODate