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

  • 项目
    每个键中
    产品
    数组的
    计数

代码:

来到您的地图还原解决方案

然而,我遇到了这样一个问题:reduce函数不是一次接收所有的“值”,而是一批一批地接收 元素

这是mongodb为每个组调用reduce函数的一种方式。从:

MongoDB可以为同一个目标多次调用reduce函数 钥匙在这种情况下,reduce函数的先前输出 该键将成为下一个reduce的输入值之一 该键的函数调用

您需要对
映射
减少
功能进行一些修改,并添加一个新的
完成
功能:

  • 您需要记住,当
    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;
        }
    }
)