Du kan enkelt aggregera resultatet istället för att välja en kartreducerande lösning:
-
Matchde poster där datumet är större än det angivna datumet. -
Groupbaserat påbrand_idfältet. -
Använd $addToSet operatör för att underhålla en
productslista över unikaproduct_idför varje grupp. -
Projectcountavproductsarray i varje tangent.
Kod:
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 till din kartreducerande lösning,
Det är ett sätt som mongodb kan anropa reduceringsfunktionen för varje grupp. Från dokumenten :
Du måste göra några ändringar på din map ,reduce funktioner och lägg till en ny finalize funktion:
- Du måste komma ihåg att när
mongodbanroparreducefunktionen för samma tangent mer än en gång skickas resultatet av föregående anrop som en ingång till reduceringsfunktionen, tillsammans med de andra värdena nästa gång reduceringsfunktionen anropas. - Första punkten, så du måste se till att indata till reduceringsfunktionen och returvärdet från reduceringsfunktionen är konstruerade på liknande sätt, så att logiken som skrivits inuti reduceringsfunktionen kan rymma bearbetning av dess eget returnerade värde i dess tidigare anrop.
- Eftersom vi inte skulle kunna hämta antalet distinkta värden när de anropas i batcher, kan vi skriva en
reducefunktion som samlar de distinktaproduct_idsför varje nyckel och skriv enfinalizefunktion som beräknar antalet av dessa unika värden.
Kod:
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;
}
}
)