Sie könnten das Ergebnis einfach aggregieren, anstatt sich für eine Map-Reduce-Lösung zu entscheiden:
-
Matchdie Datensätze, bei denen das Datum größer als gleich dem angegebenen Datum ist. -
Groupbasierend auf derbrand_idFeld. -
Verwenden Sie $addToSet Betreiber zur Pflege eines
productsListe der eindeutigenproduct_idfür jede Gruppe. -
ProjectdiecountderproductsArray in jedem Schlüssel.
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"}}}
])
Kommen wir zu Ihrer Map-Reduce-Lösung,
Auf diese Weise kann mongodb die Reduce-Funktion für jede Gruppe aufrufen. Aus den docs :
Sie müssen einige Änderungen an Ihrer map vornehmen ,reduce Funktionen und füge ein neues finalize hinzu Funktion:
- Daran müssen Sie denken, wenn
mongodbruft dasreduceauf Funktion für denselben Schlüssel mehr als einmal ausführen, wird das Ergebnis des vorherigen Aufrufs zusammen mit den anderen Werten als Eingabe an die Reduce-Funktion übergeben, wenn die Reduce-Funktion das nächste Mal aufgerufen wird. - Erster Punkt:Sie müssen also sicherstellen, dass die Eingabe für die Reduce-Funktion und der Rückgabewert der Reduce-Funktion ähnlich aufgebaut sind, sodass die in der Reduce-Funktion geschriebene Logik ihren eigenen zurückgegebenen Wert in ihren vorherigen Aufrufen verarbeiten kann.
- Da wir nicht in der Lage wären, die Anzahl der unterschiedlichen Werte abzurufen, wenn sie in Stapeln aufgerufen werden, können wir ein
reduceschreiben Funktion, die die unterschiedlichenproduct_idsakkumuliert für jeden Schlüssel und schreibe einfinalizeFunktion, die die Anzahl dieser eindeutigen Werte berechnet.
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;
}
}
)