从MongoDB聚合返回每小时的单个记录,我还需要知道字段中的“模式”或最常出现的值 .
到目前为止,我已经选择了两个日期之间的记录集,并且每小时返回一条记录,包括字段值的平均值 . 但我还需要最频繁的类别,其中类别编号字段包含1,2,3或4 .
var myName = "CollectionName"
//schema for mongoose
var mySchema = new Schema({
dt: Date,
value: Number,
category: Number
});
var myDB = mongoose.createConnection('mongodb://localhost:27017/MYDB');
myDBObj = myDB.model(myName, evalSchema, myName);
以下$ group中的日期数学创建当天每小时的记录,$ avg平均价格字段....
但我不知道如何在类别字段中返回最常出现的1,2,3或4 ...没有$ mode聚合运算符,我得到错误 "exception: unknown group operator '$mode'"
myDBObj.aggregate([
{
$match: { "dt": { $gt: new Date("October 13, 2010 12:00:00"), $lt: new Date("November 13, 2010 12:00:00") } }
},{
$group: {
"_id": {
"dt": {
"$add": [
{
"$subtract": [
{ "$subtract": ["$dt", new Date(0)] },
{
"$mod": [
{ "$subtract": ["$dt", new Date(0)] },
3600000//1000 * 60 * 60
]
}
]
},
new Date(0)
]
}
},
"price": { "$avg": "$price" },
"category" : { "$mode" : "$category"}
}
}], function (err, data) { if (err) { return next(err); } res.json(data); });
有没有办法返回字段中包含的最常见值?
我需要使用map-reduce功能吗?我如何将它们与上面的每小时聚合结合起来?感谢您的任何帮助 .
1 回答
那么你不能只是"make up" . 作为
$mode
的运算符不是攻击操作符,您可以使用的唯一内容是those that actually exist .因此,为了在最多发生的分组时间段内返回类别值,必须首先对每个值进行分组并返回出现次数 . 然后,您可以按该计数订购这些结果,并返回在该期间内记录最高计数的类别值:
所以在日期和类别上都是$group并通过$sum保留类别计数 . 然后你$sort所以最大的"count"在每个分组日期的顶部 . 当你应用另一个刚刚应用于日期本身的
$group
时,最后使用$first,以便返回每个日期具有最大计数的类别 .不要被像
$max
这样的运营商诱惑,因为它们在这里不起作用 . 关键的区别在于"tied"与每个类别值产生的"record/document"的关联 . 所以它不是你想要的最大值"count"或最大"category"值,而是"produced"最大计数的类别值 . 因此,这里需要一个$sort
.最后你应该“破坏”一些习惯:
除非您确实知道自己在做什么,否则不要使用非UTC格式的日期实例数据作为输入 . 日期将始终转换为UTC,因此至少在测试列表中,您应该习惯于指定日期值 .
它可能看起来有点干净,但是像
1000 * 60 * 60
这样的东西比3600000
更能说明它的代码 . 相同的值,但一种形式表明它的时间单位一目了然 .复合
_id
当只有一个值时也会混淆问题 . 因此,如果这是唯一存在的值,则访问_id.dt
几乎没有意义 . 什么时候_id
内不止一个属性,那就没关系了 . 但单个值应该仅仅分配回_id
. 没有什么可以获得,单一是非常清楚的 .