Potresti facilmente aggregare il risultato, invece di optare per una soluzione di riduzione della mappa:
-
Match
i record in cui la data è maggiore di uguale alla data specificata. -
Group
in base abrand_id
campo. -
Usa $addToSet operatore per mantenere un
products
elenco diproduct_id
univoci per ogni gruppo. -
Project
ilcount
deiproducts
array in ogni chiave.
Codice:
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"}}}
])
Venendo alla tua soluzione di riduzione della mappa,
Questo è un modo in cui mongodb può invocare la funzione di riduzione per ogni gruppo. Dai documenti :
Devi apportare alcune modifiche alla tua map
,reduce
funzioni e aggiungi un nuovo finalize
funzione:
- Devi ricordarlo quando
mongodb
invoca ilreduce
funzione per la stessa chiave più di una volta, il risultato dell'invocazione precedente viene passato come input alla funzione di riduzione, insieme agli altri valori alla successiva chiamata della funzione di riduzione. - Primo punto, quindi devi assicurarti che l'input della funzione reduce e il valore restituito dalla funzione reduce siano costruiti in modo simile, in modo che la logica scritta all'interno della funzione reduce possa adattarsi all'elaborazione del proprio valore restituito nelle sue precedenti chiamate.
- Dato che non saremmo in grado di recuperare il conteggio di valori distinti quando vengono chiamati in batch, ciò che possiamo fare è scrivere un
reduce
funzione che accumula i distintiproduct_ids
per ogni chiave e scrivere unfinalize
funzione che calcola il conteggio di quei valori univoci.
Codice:
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;
}
}
)