计算一个数组的数量和索引

我有一个对象的数组:

result = [ { _id: 53d0dfe3c42047c81386df9d, video_id: '1' }, { _id: 53d0dfe3c42047c81386df9e, video_id: '1' }, { _id: 53d0dfe3c42047c81386df9f, video_id: '1' }, { _id: 53d0dfe3c42047c81386dfa0, video_id: '2' }, { _id: 53d0dfe3c42047c81386dfa1, video_id: '2' }, { _id: 53d0dfe3c42047c81386dfa2, video_id: '1' }, { _id: 53d0dfe3c42047c81386dfa3, video_id: '2' }, { _id: 53d0dfe3c42047c81386dfa4, video_id: '1' } ] 

我需要创build另一个数组,它将video_id作为索引,并且包含这个video_id出现在第一个数组中的次数:

 list = [ {'1' : 5}, {'2' : 4} ] 

目前,我使用这个代码:

 while (i < result.length) { if(list[result[i].video_id] === undefined) { list[result[i].video_id] = 0; } list[result[i].video_id] = list[result[i].video_id] + 1; i = i + 1; } 

它可行,但我不知道有没有更快更清洁的方法呢? (真正的结果数组有超过10k的元素,我怀疑> 10k条件语句是最佳的…)。

我正在使用node.js,结果来自一个mongoose(mongoDB)查询,我没有看到有任何方法可以通过mongoose本身完成:

 var now = new Date(); //M_logs is a mongoose model query = M_logs.where('time').gt(new Date(now.getFullYear(), 0, 1).getTime() / 1000).lt(now.getTime() / 1000).select('video_id'); 

(PS:我不知道这是不是一个代码审查问题,请告诉我,如果我是脱离主题,所以我可以迁移的问题)。

编辑:

回答Juan Carlos Farah:

 S_logs = new mongoose.Schema({ user_ip : String, user_id : String, user_agent : String, canal_id : String, theme_id : String, video_id : String, osef : String, time : Number, action: String, is_newuser : String, operator : String, template : String, catalogue : String, referer : String, from : String, osef1 : String }); M_logs = mongoose.model('logs', S_logs); 

你可以使用聚合框架来做到这一点。 这个想法是做一些事情如下:

  1. 匹配你正在寻找的文件。 基于您当前的查询,我知道这将是文档time介于new Date(now.getFullYear(), 0, 1).getTime() / 1000now.getTime() / 1000
  2. 通过video_id对匹配的文档进行video_id并logging它们的计数。
  3. 可以通过_idsorting,这相当于原始的video_id

以下是mongo shell语法:

 var now = new Date(); db.M_logs.aggregate([ { "$match" : { "time" : { "$gt" : new Date(now.getFullYear(), 0, 1).getTime() / 1000, "$lt" : now.getTime() / 1000 } } }, { "$group" : { "_id" : "$video_id", "count" : { "$sum" : 1 } } }, { "$sort" : { "_id" : 1 } } ]); 

如果这对你有效,你可以很容易地在Mongoose或Node.js驱动程序语法中实现它。 请注意,聚合框架返回一个游标,您可以遍历该游标来填充数组。

编辑:

使用Node.js驱动程序,您可以访问callback函数中聚合查询的结果。 如下所示:

 ... , function(err, result) { console.dir(result); db.close(); } 

请注意,聚合查询的Mongoose语法略有不同。

例:

 Model.aggregate([ <QUERY> ]).exec( <CALLBACK> ); 

有关更多信息,请参阅此处的文档。

我build议你使用聚合框架来统计文档的数量。 这将比迭代所有文档并计算它们快得多。

使用mongoose,你可以这样做:

 var now = new Date(); var startTime = new Date(now.getFullYear(), 0, 1).getTime() / 1000): var endTime = now.getTime() / 1000; M_logs.aggregate([ // filter the documents you're looking for {"$match" : { "time" : {"$gt": startTime, "$lt": endTime}}}, // group by to get the count for each video_id {"$group" : {"_id" : "$video_id", "count" : {"$sum" : 1}}}, // make the output more explanatory; this part is optional {"$project" : { "video_id" : "$_id", "count" : "$count", _id : 0}} ]).exec(function(err, docs){ if (err) console.err(err); console.log(docs); }); 

docs的输出将是:

 [ { count: 4, video_id: '2' }, { count: 5, video_id: '1' } ] 

使用

 var list = {}; result.forEach(function (el) { list[el.video_id] = (list[el.video_id] || 0) + 1; }); 

结果列表看起来像这样:

 var list = { '1': 5, '2': 4 };