Podría agregar fácilmente el resultado, en lugar de optar por una solución de reducción de mapas:
-
Matchlos registros donde la fecha es mayor que igual a la fecha especificada. -
Groupbasado en elbrand_idcampo. -
Use el $addToSet operador para mantener un
productslista deproduct_idúnicos para cada grupo. -
Projectelcountde losproductsmatriz en cada tecla.
Código:
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"}}}
])
Llegando a su solución de reducción de mapas,
Esa es una forma en que mongodb puede invocar la función de reducción para cada grupo. De los docs :
Necesitas hacer alguna modificación a tu map ,reduce funciones y agregar un nuevo finalize función:
- Debe recordar que cuando
mongodbinvoca elreducefunción para la misma clave más de una vez, el resultado de la invocación anterior se pasa como entrada a la función reduce, junto con los otros valores la próxima vez que se invoca la función reduce. - Primer punto, por lo que debe asegurarse de que la entrada a la función de reducción y el valor de retorno de la función de reducción estén construidos de manera similar, de modo que la lógica escrita dentro de la función de reducción pueda acomodar el procesamiento de su propio valor devuelto en sus llamadas anteriores.
- Dado que no podríamos recuperar el recuento de valores distintos cuando se llaman por lotes, lo que podemos hacer es escribir un
reducefunción que acumula los distintosproduct_idspara cada tecla y escriba unfinalizefunción que calcula el recuento de esos valores únicos.
Código:
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;
}
}
)