Du kan nemt samle resultatet i stedet for at vælge en kortreducerende løsning:
-
Matchde poster, hvor datoen er større end lig med den angivne dato. -
Groupbaseret påbrand_idfelt. -
Brug $addToSet operatør til at vedligeholde et
productsliste over uniktproduct_idfor hver gruppe. -
Projectcountafproductsarray i hver tast.
Kode:
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"}}}
])
Kommer til din kortreducerende løsning,
Det er en måde, mongodb kan påberåbe reduktionsfunktionen for hver gruppe. Fra dokumenterne :
Du skal lave nogle ændringer på dit map ,reduce funktioner og tilføje en ny finalize funktion:
- Du skal huske, at når
mongodbpåberåberreducefunktion for den samme tast mere end én gang, sendes resultatet af den forrige påkaldelse som input til reduktionsfunktionen sammen med de andre værdier, næste gang reduktionsfunktionen aktiveres. - Første punkt, så du skal sikre dig, at input til reduceringsfunktionen og returværdien fra reduceringsfunktionen er konstrueret på samme måde, så logikken skrevet inde i reducerfunktionen kan rumme behandling af dens egen returnerede værdi i dens tidligere kald.
- Da vi ikke ville være i stand til at hente antallet af distinkte værdier, når de kaldes i batches, kan vi skrive en
reducefunktion, der akkumulerer de distinkteproduct_idsfor hver tast og skriv enfinalizefunktion, der beregner antallet af disse unikke værdier.
Kode:
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;
}
}
)