我有以下猫鼬模型:
var MobileAppSchema = mongoose.Schema({
identifier: String,
...
});
var RecordingSchema = mongoose.Schema({
... ,
app: {
type: mongoose.Schema.Types.ObjectId,
ref: 'MobileApp'
},
length: Number,
...
});
现在我得到一些MobileAppSchema的记录,我希望得到所有RecordingSchemas,其中Recording.app等于我的一个MobileApps。对于所有获取的文档,我想获得Recording.length的平均值。
我当前的方法有效,但是我想直接与mongoose查询聚合,而不是之后。
目前的实施:
exports.averageTimeSpentForAppIdentifier = function(appIdentifier, done) {
mobileAppsForAppIdentifier(appIdentifier, function(err, mobileApps) {
if(err) {
return done(err);
}
var appIds = mobileApps.map(function(mobileApp) {return mobileApp._id;});
Recording.find({
'app': { $in: appIds}}, function(err, recordings) {
if(err) {
return done(err);
}
if(!recordings || recordings.length == 0) {
return done(null, 0);
}
var average = recordings
.map(function(recording,i,arr) {
return recording.length/arr.length
})
.reduce(function(a,b) {
return a + b
});
done(null, average);
});
});
};
答案 0 :(得分:2)
汇总框架可供您使用。运行以下管道将为您提供所需的结果。它使用 $match
管道作为过滤掉进入聚合的文档的初始步骤
没有制定mobileApps id的给定标准的管道。
后面的 $group
运算符用于主聚合,即使用 $avg
累加器运算符计算分组文档的平均长度:
exports.averageTimeSpentForAppIdentifier = function(appIdentifier, done) {
mobileAppsForAppIdentifier(appIdentifier, function(err, mobileApps) {
if(err) {
return done(err);
}
var appIds = mobileApps.map(function(mobileApp) {return mobileApp._id;}),
pipeline = [
{"$match": { "app": { $in: appIds } } },
{
"$group": {
"_id": null,
"average": { "$avg": "$length" }
}
}
];
Recording.aggregate(pipeline)
.exec(function (err, result){
if(err) {
return done(err);
}
done(null, result[0].average);
})
// Or using the fluent pipeline builder API
Recording.aggregate()
.match({ "app": { $in: appIds } })
.group({ "_id": null, "average": { "$avg": "$length" }})
.exec(function (err, result){
if(err) {
return done(err);
}
done(null, result[0].average);
});
});
};