Mongodb Mongo地图简化为模拟;计数(独立(…)组“;SQL中的by
我想知道在一段时间内,每个品牌销售了多少独特的产品。单个文档看起来像:Mongodb Mongo地图简化为模拟;计数(独立(…)组“;SQL中的by,mongodb,Mongodb,我想知道在一段时间内,每个品牌销售了多少独特的产品。单个文档看起来像: { brand_id: 1, product_id: 2, date: ISODate("2014-12-12") } 在SQL中,这将是:selectbrand\u-id,count(distinct(product\u-id))与订单中的日期。。。按品牌标识分组 我想不出通过Mongo的聚合框架(group之类)实现这一点的方法。这是我现在的地图: db.orders.mapReduce(
{
brand_id: 1,
product_id: 2,
date: ISODate("2014-12-12")
}
在SQL中,这将是:selectbrand\u-id,count(distinct(product\u-id))与订单中的日期。。。按品牌标识分组
我想不出通过Mongo的聚合框架(group之类)实现这一点的方法。这是我现在的地图:
db.orders.mapReduce(
function() {
emit(this.brand_id, this.product_id);
},
function(key, values) {
return values.filter(function (value, index, self) {return self.indexOf(value) === index;}).length;
},
{
query: {date: {$gte: new Date('2014-11-20')}},
out: "example"
}
)
这看起来很好。然而,我遇到了一个问题,reduce函数不是一次接收所有的“值”,而是以101个元素为一批。因此,任何查找唯一值的尝试都会失败,我得到的只是上次调用reduce函数时唯一元素的数量。我不知道如何利用这里的“finalize”属性来获得我想要的东西
任何想法都将不胜感激
我在Mongo2.4和2.6上尝试了这个,只是为了确保它不是版本问题
我想不出通过Mongo的聚合框架(group之类)实现这一点的方法
您可以轻松聚合结果,而不是选择map reduce解决方案:
匹配日期大于等于 指定日期
根据
字段分组品牌标识
- 使用操作员维护
唯一产品列表 每组的产品
产品id
每个键中项目
数组的产品
计数
映射
,减少
功能进行一些修改,并添加一个新的完成
功能:
- 您需要记住,当
调用mongodb
同一个键的功能不止一次,前一个键的结果 调用作为输入传递给reduce函数,以及 下一次调用reduce函数时的其他值reduce
- 第一点,所以您需要确保reduce的输入 函数和reduce函数的返回值类似 构造,这样写在reduce函数中的逻辑就可以 允许在以前的调用中处理自己的返回值
- 因为我们将无法检索不同值的计数
批量调用时,我们可以做的是编写一个
函数 为每个键累积不同的reduce
,并写入产品ID
函数,用于计算这些唯一值的计数finalize
db.collection.mapReduce(
函数(){
//发出reduce函数返回的相同结构。
emit(this.brand_id,{“prod_id”:[this.product_id]});
},
功能(键、值){
//返回值将是唯一产品标识的列表。
var res={“prod_id”:[]};
对于(var i=0;在管道的$project步骤中使用$size聚合函数需要Mongo 2.6
db.collection.aggregate([
{$match:{"date":{$gte:new Date('2014-11-20')}}},
{$group:{"_id":"$brand_id","products":{$addToSet:"$product_id"}}},
{$project:{"_id":0,"brand_id":"$_id","distinct_prod":{$size:"$products"}}}
])
db.collection.mapReduce(
function() {
// emitting the same structure returned by the reduce function.
emit(this.brand_id, {"prod_id":[this.product_id]});
},
function(key, values) {
// the return value would be a list of unique product_ids.
var res = {"prod_id":[]};
for(var i=0;i<values.length;i++)
{
for(var j=0;j<values[i].prod_id.length;j++){
if(res.prod_id.indexOf(values[i].prod_id[j]) == -1){
res.prod_id.push(values[i].prod_id[j]);
}
}}
return res;
},
{
query: {date: {$gte: new Date('2014-11-20')}},
out: "example",
finalize: function(key, reducedValue){
// it returns just the count
return reducedValue.prod_id.length;
}
}
)