Javascript 使用mongodb聚合框架计算频率

Javascript 使用mongodb聚合框架计算频率,javascript,node.js,mongodb,aggregation-framework,nosql,Javascript,Node.js,Mongodb,Aggregation Framework,Nosql,我试图根据10秒的间隔计算数据库中文档的频率 以下是我的数据库对象的外观: [ { created_at: "2014-03-31T22:30:48.000Z", id: 450762158586880000, _id: "5339ec9808eb125965f2eae1" }, { created_at: "2014-03-31T22:30:48.000Z", id: 450762160407597060, _id: "5

我试图根据10秒的间隔计算数据库中文档的频率

以下是我的数据库对象的外观:

[
  {
     created_at: "2014-03-31T22:30:48.000Z",
     id: 450762158586880000,
     _id: "5339ec9808eb125965f2eae1"
  },
  {
     created_at: "2014-03-31T22:30:48.000Z",
     id: 450762160407597060,
     _id: "5339ec9808eb125965f2eae2"
  },
  {
     created_at: "2014-03-31T22:30:49.000Z",
     id: 450762163482017800,
     _id: "5339ec9908eb125965f2eae3"
  },
  {
     created_at: "2014-03-31T22:30:49.000Z",
     id: 450762166367707140,
     _id: "5339ec9908eb125965f2eae4"
  },
  {
     created_at: "2014-03-31T22:30:50.000Z",
     id: 450762167412064260,
     _id: "5339ec9a08eb125965f2eae5"
  }
]
[
  {
     time_from: "2014-03-31T22:30:48.000Z",
     time_to: "2014-03-31T22:30:58.000Z",
     count: 6
  },
  {
     time_from: "2014-03-31T22:30:58.000Z",
     time_to: "2014-03-31T22:31:08.000Z",
     count: 3
  },
  {
     time_from: "2014-03-31T22:31:08.000Z",
     time_to: "2014-03-31T22:31:18.000Z",
     count: 10
  },
  {
     time_from: "2014-03-31T22:31:18.000Z",
     time_to: "2014-03-31T22:31:28.000Z",
     count: 1
  },
  {
     time_from: "2014-03-31T22:31:28.000Z",
     time_to: "2014-03-31T22:31:38.000Z",
     count: 3
  }
]
我已经设法显示了给定间隔内的频率,但我希望每10秒显示一次。因此,我的JSON最好如下所示:

[
  {
     created_at: "2014-03-31T22:30:48.000Z",
     id: 450762158586880000,
     _id: "5339ec9808eb125965f2eae1"
  },
  {
     created_at: "2014-03-31T22:30:48.000Z",
     id: 450762160407597060,
     _id: "5339ec9808eb125965f2eae2"
  },
  {
     created_at: "2014-03-31T22:30:49.000Z",
     id: 450762163482017800,
     _id: "5339ec9908eb125965f2eae3"
  },
  {
     created_at: "2014-03-31T22:30:49.000Z",
     id: 450762166367707140,
     _id: "5339ec9908eb125965f2eae4"
  },
  {
     created_at: "2014-03-31T22:30:50.000Z",
     id: 450762167412064260,
     _id: "5339ec9a08eb125965f2eae5"
  }
]
[
  {
     time_from: "2014-03-31T22:30:48.000Z",
     time_to: "2014-03-31T22:30:58.000Z",
     count: 6
  },
  {
     time_from: "2014-03-31T22:30:58.000Z",
     time_to: "2014-03-31T22:31:08.000Z",
     count: 3
  },
  {
     time_from: "2014-03-31T22:31:08.000Z",
     time_to: "2014-03-31T22:31:18.000Z",
     count: 10
  },
  {
     time_from: "2014-03-31T22:31:18.000Z",
     time_to: "2014-03-31T22:31:28.000Z",
     count: 1
  },
  {
     time_from: "2014-03-31T22:31:28.000Z",
     time_to: "2014-03-31T22:31:38.000Z",
     count: 3
  }
]
这就是我到目前为止所做的:

exports.findAll = function (req, res) {
    db.collection(collection_name, function (err, collection) {
        collection.find().toArray(function (err, items) {
            collection.find().sort({"_id": 1}).limit(1).toArray(function (err, doc) {
                var interval = 100000; // in milliseconds
                var startTime = doc[0].created_at;
                var endTime = new Date(+startTime + interval);

                collection.aggregate([
                    {$match: {"created_at": {$gte: startTime, $lt: endTime}}},
                    {$group: {"_id": 1, "count":{$sum: 1}}}
                ], function(err, result){
                    console.log(result);
                    res.send(result);
                });
            });
        })
    });
};
这就是结果:

[
  {
     _id: 1,
     count: 247
  }
]
编辑:

其结果是:

[
  {
     _id: {
        year: 2014,
        month: 3,
        day: 31,
        hour: 22,
        minute: 37,
        second: 10
     },
     count: 6
  }, ...

新的进度,现在我如何在10秒的间隔内显示它?

如果它只是在10秒的间隔内得到一些东西,您可以做一点数学运算,然后通过聚合运行以下内容:

db.collection.aggregate([
{“$组”:{
“_id”:{
“年”:{“$year”:“$created_at”},
“月”:{“$month”:“$created_at”},
“day”:{“$dayOfMonth”:“$created_at”},
“小时”:{“$hour”:“$created_at”},
“分钟”:{“$minute”:“$created_at”},
“第二个”:{“$subtract”:[
{“$second”:“$created_at”},
{“$mod”:[
{“$second”:“$created_at”},
10
]}
]}
},
“计数”:{“$sum”:1}
}}
])
这将事情分解为一分钟内10秒的时间间隔,在这个时间间隔内,它们通过一个mod 10数学模型发生

我认为这是合理的,并且将是最快的跑步者,因为它使用聚合。如果您确实需要从最初匹配的时间开始运行10秒的序列,则可以使用mapReduce执行此过程:

首先是地图绘制者:

var映射器=函数(){
if(此.created_位于.getTime()>(最后日期+10000)){
如果(最后日期==0){
last_date=this.created_at.getTime();
}否则{
最后_日期+=10000;
}
}
散发(
{
开始:新日期(最后一天),
结束:新日期(最后一天+10000)
},
这是在
);
}
因此,这将在10秒的时间间隔内发出日期,从第一个日期开始,然后在每次发现超出范围的内容时增加时间间隔

现在您需要一个减速器:

var reducer=函数(键、值){
返回值.length;
};
很简单。只需返回传入的数组的长度

因为mapReduce的工作方式是这样的,所以任何不具有多个值的内容都不会传递给reducer,所以请使用finalize进行清理:

var finalize=函数(键、值){
if(类型(值)=“对象”){
数值=1;
}
返回值;
};
然后运行它以获得结果。请注意“范围”部分,该部分传递要在映射器中使用的全局变量:

db.collection.mapReduce(
制图员,
减速器,
{ 
“out”:{“inline”:1},
“范围”:{“最后日期”:0},
“最终确定”:最终确定
}
)
每种方法可能会产生略有不同的结果,但这就是重点。这取决于你到底想用哪一个


考虑到您的评论,您可以“检查”任一语句的输出,也可以按原样编程“填补空白”。我通常更喜欢这个选项,但它不是我的程序,我不知道您试图从这个查询中检索的序列有多大

在服务器端,您可以修补“映射器”以执行以下操作:

var映射器=函数(){
if(此.created_位于.getTime()>(最后日期+10000)){
如果(最后日期==0){
last_date=this.created_at.getTime();
}否则{
//修补空块
var时间=数学地板(
(此.created_位于.getTime()-最后日期)/10000
);
如果(次数>1){
对于(变量i=1;i
这是我要寻找的90%,但我希望在没有数据的情况下得到value=0。Aggregate只是跳过这个位置,mapReduce似乎将值设为=1,即使文档没有在该时间间隔内创建。有什么想法吗?再次感谢您发布的内容@knowbody我几乎只是发表了一个评论,但实际内容被添加到了解释和解决的答案中。@knowbody没问题。这是一个很好的问题,回答得很好。我很高兴你在这方面比大多数人付出了更多的努力。那么,当我的数据格式如下:
{“data”:{“interaction”:{“created_at”:“Wed,09 Apr 2014 14:38:16+0000”},{id:{“$oid”:“53455b59edcd5e4e3fdd4eb”}
我将在
var mapper
中放入什么?我尝试了
这个.data.interaction.created\u,但没有work@knowbody虽然我知道有一种诱惑,那就是回到为你提出的问题提供答案的人身边。正确的格式是提交一个关于stackoverflow的新问题。因此,如果你想得到回应,请咨询社区。评论不是提出新问题的地方。