Você pode agregar facilmente o resultado, em vez de optar por uma solução de redução de mapa:
-
Match
os registros onde a data é maior que igual à data especificada.
-
Group
com base nobrand_id
campo.
-
Use o $addToSet operador para manter umproducts
lista deproduct_id
exclusivos para cada grupo.
-
Project
acount
dosproducts
matriz em cada chave.
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"}}}
])
Chegando à sua solução de redução de mapas,
Essa é uma maneira que o mongodb pode invocar a função de redução para cada grupo. Dos documentos :
Você precisa fazer alguma modificação em seu
map
,reduce
funções e adicione um novo finalize
função:- Você precisa se lembrar disso quando
mongodb
invoca oreduce
função para a mesma chave mais de uma vez, o resultado da invocação anterior é passado como uma entrada para a função de redução, juntamente com os outros valores na próxima vez que a função de redução for invocada. - Primeiro ponto, então você precisa garantir que a entrada para a função reduce e o valor de retorno da função reduce sejam construídos de forma semelhante, para que a lógica escrita dentro da função reduce possa acomodar o processamento de seu próprio valor retornado em suas chamadas anteriores. l>
- Como não poderíamos recuperar a contagem de valores distintos quando chamados em lotes, o que podemos fazer é escrever um
reduce
função que acumula os distintosproduct_ids
para cada chave e escreva umfinalize
função que calcula a contagem desses valores exclusivos.
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;
}
}
)