Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Date mongodb中的按日期分组_Date_Group By_Mongodb - Fatal编程技术网

Date mongodb中的按日期分组

Date mongodb中的按日期分组,date,group-by,mongodb,Date,Group By,Mongodb,我正在做一个项目,在这个项目中我跟踪某个主题的点击次数 我正在使用mongodb,我必须按日期对点击次数进行分组(我想将数据分组15天) 我在mongodb中有以下格式的数据存储 { "_id" : ObjectId("4d663451d1e7242c4b68e000"), "date" : "Mon Dec 27 2010 18:51:22 GMT+0000 (UTC)", "topic" : "abc", "time" : "18:51:22" } { "

我正在做一个项目,在这个项目中我跟踪某个主题的点击次数

我正在使用mongodb,我必须按日期对点击次数进行分组(我想将数据分组15天)

我在mongodb中有以下格式的数据存储

{ 
   "_id" : ObjectId("4d663451d1e7242c4b68e000"), 
  "date" : "Mon Dec 27 2010 18:51:22 GMT+0000 (UTC)", 
  "topic" : "abc", 
  "time" : "18:51:22"
}
{ 
    "_id" : ObjectId("4d6634514cb5cb2c4b69e000"), 
    "date" : "Mon Dec 27 2010 18:51:23 GMT+0000 (UTC)", 
    "topic" : "bce", 
    "time" : "18:51:23"
}
db.getCollection('supportIssuesChat').aggregate([
{
        $group : {
           _id :{ $dateToString: { format: "%Y-%m-%d", date: "$createdAt"} },
           list: { $push: "$$ROOT" },
           count: { $sum: 1 }
        }
}
])
我想按天对主题:abc的点击次数进行分组(15天)…我知道如何分组,但如何按存储在数据库中的日期分组

我正在寻找以下格式的结果

[
  {
    "date" : "date in log",
    "click" : 9 
  },  
  {
    "date" : "date in log",
    "click" : 19
  },  
]
我已经写了代码,但只有当日期是字符串时它才会工作(代码在这里)
…请指导我如何对它进行分组

我还没有在MongoDB上进行过很多工作,所以我不能完全确定。但是您不能使用完整的Javascript吗?
因此,您可以使用Javascript
date
class解析日期,创建日期,并将其设置为“out”属性的键。如果密钥已经存在,则始终添加一个,否则使用value=1(第一次单击)创建新密钥。下面是您的代码,带有调整的reduce函数(未测试的代码!):


延迟回答,但为了记录(对于来到本页的任何其他人):您需要使用“keyf”参数而不是“key”,因为您的key实际上是事件日期的函数(即从日期中提取的“day”),而不是日期本身。这应该满足您的需求:

db.coll.group(
{
    keyf: function(doc) {
        var date = new Date(doc.date);
        var dateKey = (date.getMonth()+1)+"/"+date.getDate()+"/"+date.getFullYear()+'';
        return {'day':dateKey};
    },
    cond: {topic:"abc"},
    initial: {count:0},
    reduce: function(obj, prev) {prev.count++;}
});

有关更多信息,请查看MongoDB关于聚合和组的文档页面:

另一个迟来的答案,但仍然是。因此,如果您只想在一次迭代中完成,并获得按日期和主题分组的点击次数,您可以使用以下代码:

db.coll.group(
{
   $keyf : function(doc) {
       return { "date" : doc.date.getDate()+"/"+doc.date.getMonth()+"/"+doc.date.getFullYear(),
                "topic": doc.topic };
    },
    initial: {count:0},
    reduce: function(obj, prev) { prev.count++; }
 })
另外,如果您希望按照建议优化查询,您可以对日期使用整数值(提示:使用valueOf()),而不是字符串,尽管对于我的示例,速度是相同的


此外,定期检查MongoDB文档始终是明智的,因为它们一直在添加新功能。例如,使用新的聚合框架(将在2.2版本中发布),您可以更轻松地获得相同的结果。

感谢@MindTheep,您的回答帮助解决了我今天的问题。下面的功能可以小组一天比一天轻松一点,希望能帮助其他人

/**
 * group by day
 * @param query document {key1:123,key2:456}
 */
var count_by_day = function(query){
    return db.action.group(
    {
        keyf: function(doc) {
            var date = new Date(doc.time);
            var dateKey = (date.getMonth()+1)+"/"+date.getDate()+"/"+date.getFullYear();
            return {'date': dateKey};
        },
        cond:query,
        initial: {count:0},
        reduce: function(obj, prev) {
          prev.count++;
        }
    });
}

count_by_day({this:'is',the:'query'})
使用Mongo聚合框架的新答案 在回答了这个问题后,10gen发布了带有聚合框架的Mongodb 2.2版,这是执行此类查询的更好方法。此查询有点挑战性,因为您希望按日期分组,并且存储的值是时间戳,因此您必须做些事情将时间戳转换为匹配的日期。出于示例的目的,我将只编写一个获得正确计数的查询

db.col.aggregate(
{$group:{{u id:{$dayOfYear:$date},
单击:{$sum:1}}
)
这将返回如下结果:

[
{
“_id”:144,
“点击”:165
},
{
“_id”:275,
“点击”:12
}
]
您需要使用
$match
将查询限制在您感兴趣的日期范围内,并使用
$project
\u id
重命名为
日期
。如何将一年中的某一天转换回某个日期留给读者作为练习。:-)

10gen有一个方便的书签。还有一篇关于这个问题的专门文章

如果您有点喜欢,您可以使用:

db.col.aggregate([
{$group:{
_身份证:{
$add:[
{$dayOfYear:“$date”},
{$乘法:
[400,{$year:$date}]
}
]},   
单击:{$sum:1},
第一:{$min:$date}
}
},
{$sort:{u id:-1}},
{$限额:15},
{$project:{日期:$first',单击:1,_id:0}
])
这将为您提供最新的15天,并在
date
字段中返回每天内的一些datetime。例如:

[
{
“点击”:431,
“日期”:ISODate(“2013-05-11T02:33:45.526Z”)
},
{
“点击”:702,
“日期”:ISODate(“2013-05-08T02:11:00.503Z”)
},
...
{
“点击”:814,
“日期”:ISODate(“2013-04-25T00:41:45.046Z”)
}
]
如果您希望直接返回 然后应用“日期数学”对日期对象进行取整,而不是应用。这通常是可取的,因为所有驱动程序都以一种形式表示BSON日期,这种形式通常用于所有语言的日期操作,如果可能的话:

db.datetest.aggregate([
{“$组”:{
“_id”:{
“$add”:[
{“$subtract”:[
{“$subtract”:[“$date”,新日期(0)],
{“$mod”:[
{“$subtract”:[“$date”,新日期(0)],
1000 * 60 * 60 * 24
]}
]},
新日期(0)
]
},
“单击”:{“$sum”:1}
}}
])
或者,如果问题中暗示所需的分组间隔为15天的“桶”,则只需将其应用于
$mod
中的数值:

db.datetest.aggregate([
{“$组”:{
“_id”:{
“$add”:[
{“$subtract”:[
{“$subtract”:[“$date”,新日期(0)],
{“$mod”:[
{“$subtract”:[“$date”,新日期(0)],
1000 * 60 * 60 * 24 * 15
]}
]},
新日期(0)
]
},
“单击”:{“$sum”:1}
}}
])
应用的基本数学是,当两个
Date
对象时,返回的结果将是数值差异的毫秒数。因此,epoch由
Date(0)
表示,作为使用任何语言构造函数进行转换的基础

对于数值,“模”()用于将日期四舍五入(从除法中减去余数)为
{'$project': {
    'start_of_day': {'$subtract': [
        '$date',
        {'$add': [
            {'$multiply': [{'$hour': '$date'}, 3600000]},
            {'$multiply': [{'$minute': '$date'}, 60000]},
            {'$multiply': [{'$second': '$date'}, 1000]},
            {'$millisecond': '$date'}
        ]}
    ]},
}}
{
    "start_of_day" : ISODate("2015-12-03T00:00:00.000Z")
},
{
    "start_of_day" : ISODate("2015-12-04T00:00:00.000Z")
}
return new Promise(function(resolve, reject) {
db.doc.aggregate(
            [
                { $match: {} },
                { $group: { _id: { $dateToString: { format: "%Y-%m-%d", date: "$date" } }, count: { $sum: 1 } } },
                { $sort: { _id: 1 } }
            ]
        ).then(doc => {
            /* if you need a date object */
            doc.forEach(function(value, index) {
                  doc[index]._id = new Date(value._id);
              }, this);
            resolve(doc);
        }).catch(reject);
}
db.getCollection('supportIssuesChat').aggregate([
{
        $group : {
           _id :{ $dateToString: { format: "%Y-%m-%d", date: "$createdAt"} },
           list: { $push: "$$ROOT" },
           count: { $sum: 1 }
        }
}
])