U kunt het resultaat gemakkelijk samenvoegen, in plaats van te kiezen voor een kaartverkleinende oplossing:
-
Match
de records waarvan de datum groter is dan de opgegeven datum. -
Group
gebaseerd op debrand_id
veld. -
Gebruik de $addToSet operator om een
products
te onderhouden lijst met uniekeproduct_id
voor elke groep. -
Project
decount
van deproducts
array in elke toets.
Code:
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"}}}
])
Komt naar uw oplossing voor het verkleinen van de kaart,
Dat is een manier waarop mongodb de reductiefunctie voor elke groep kan aanroepen. Uit de docs :
Je moet wat aanpassingen maken aan je map
,reduce
functies en voeg een nieuwe finalize
toe functie:
- Je moet onthouden dat wanneer
mongodb
roept dereduce
. op functie voor dezelfde toets meer dan eens gebruikt, wordt het resultaat van de vorige aanroep doorgegeven als invoer voor de functie reduceren, samen met de andere waarden de volgende keer dat de functie reduceren wordt aangeroepen. - Eerste punt, dus je moet ervoor zorgen dat de invoer voor de reducefunctie en de retourwaarde van de reduce-functie op dezelfde manier zijn geconstrueerd, zodat de logica die in de reduce-functie is geschreven, de verwerking van zijn eigen geretourneerde waarde in zijn eerdere aanroepen kan verwerken. li>
- Omdat we het aantal verschillende waarden niet kunnen ophalen wanneer ze in batches worden aangeroepen, kunnen we een
reduce
schrijven functie die de verschillendeproduct_ids
verzamelt voor elke sleutel en schrijf eenfinalize
functie die het aantal van die unieke waarden berekent.
Code:
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;
}
}
)