Du kan nemt samle resultatet i stedet for at vælge en kortreducerende løsning:
-
Match
de poster, hvor datoen er større end lig med den angivne dato. -
Group
baseret påbrand_id
felt. -
Brug $addToSet operatør til at vedligeholde et
products
liste over uniktproduct_id
for hver gruppe. -
Project
count
afproducts
array 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
mongodb
påberåberreduce
funktion 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
reduce
funktion, der akkumulerer de distinkteproduct_ids
for hver tast og skriv enfinalize
funktion, 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;
}
}
)