我有一个对象数组:
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' }
]
我需要创建另一个数组,它将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个元素,我怀疑&gt; 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:我想知道这不是更多的Code Review问题,请告诉我,如果我偏离主题,那么我可以移植问题。)
编辑:
回答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);
答案 0 :(得分:2)
您可以使用聚合框架执行此操作。我的想法是做如下的事情:
time
介于new Date(now.getFullYear(), 0, 1).getTime() / 1000
和now.getTime() / 1000
之间的文档。video_id
对匹配的文件进行分组,并跟踪其数量。_id
排序,这与原始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驱动程序,您可以在回调函数中访问聚合查询的结果。如下:
...
, function(err, result) {
console.dir(result);
db.close();
}
请注意,聚合查询的Mongoose语法略有不同。
示例:
Model.aggregate([ <QUERY> ]).exec( <CALLBACK> );
有关详细信息,请参阅文档here。
答案 1 :(得分:1)
我建议您使用aggregation framework来计算文档数量。它将比迭代所有文档并计算它们快得多。
使用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' } ]
答案 2 :(得分:0)
使用
var list = {};
result.forEach(function (el) {
list[el.video_id] = (list[el.video_id] || 0) + 1;
});
结果清单看起来像这样:
var list = {
'1': 5,
'2': 4
};