Sie könnten das Ergebnis einfach aggregieren, anstatt sich für eine Map-Reduce-Lösung zu entscheiden:
-
Match
die Datensätze, bei denen das Datum größer als gleich dem angegebenen Datum ist. -
Group
basierend auf derbrand_id
Feld. -
Verwenden Sie $addToSet Betreiber zur Pflege eines
products
Liste der eindeutigenproduct_id
für jede Gruppe. -
Project
diecount
derproducts
Array 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
mongodb
ruft dasreduce
auf 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
reduce
schreiben Funktion, die die unterschiedlichenproduct_ids
akkumuliert für jeden Schlüssel und schreibe einfinalize
Funktion, 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;
}
}
)