Możesz łatwo zagregować wynik, zamiast decydować się na rozwiązanie z redukcją mapy:
-
Match
rekordy, w których data jest większa niż równa podanej dacie. -
Group
na podstawiebrand_id
pole. -
Użyj $addToSet operator do obsługi
products
lista unikalnychproduct_id
dla każdej grupy. -
Project
count
products
w każdym klawiszu.
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"}}}
])
Przechodząc do rozwiązania do redukcji map,
Jest to jeden ze sposobów, w jaki mongodb może wywołać funkcję Reduce dla każdej grupy. Z dokumentacji :
Musisz dokonać pewnych modyfikacji map
,reduce
funkcje i dodaj nowy finalize
funkcja:
- Musisz o tym pamiętać, gdy
mongodb
wywołujereduce
funkcji dla tego samego klucza więcej niż raz, wynik poprzedniego wywołania jest przekazywany jako dane wejściowe do funkcji Reduce, wraz z innymi wartościami przy następnym wywołaniu funkcji Reduce. - Pierwszy punkt, musisz więc upewnić się, że dane wejściowe funkcji Reduce i wartość zwracana przez funkcję Reduce są podobnie skonstruowane, tak aby logika napisana wewnątrz funkcji Reduce umożliwiała przetwarzanie własnej wartości zwracanej w jej poprzednich wywołaniach.
- Ponieważ nie bylibyśmy w stanie pobrać liczby odrębnych wartości w przypadku wywołania w partiach, możemy napisać
reduce
funkcja, która gromadzi różneproduct_ids
dla każdego klucza i napiszfinalize
funkcja, która oblicza liczbę tych unikalnych wartości.
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;
}
}
)