Po pierwsze, Mongo map/reduce nie jest przeznaczone do użycia jako narzędzie zapytań (jak w CouchDB), jest przeznaczone do uruchamiania zadań w tle. Używam go w pracy do analizy danych o ruchu.
Jednak to, co robisz źle, to to, że stosujesz sort() do swoich danych wejściowych, ale jest to bezużyteczne, ponieważ gdy map()
etap jest zakończony, dokumenty pośrednie są sortowane według keys
. Ponieważ Twój klucz jest dokumentem, jest sortowany według product_id
, popularity
.
W ten sposób wygenerowałem mój zbiór danych
function generate_dummy_data() {
for (i=2; i < 1000000; i++) {
db.foobar.save({
_id: i,
category_id: parseInt(Math.random() * 30),
popularity: parseInt(Math.random() * 50)
})
}
}
A to moja mapa/redukcja zadania:
var data = db.runCommand({
'mapreduce': 'foobar',
'map': function() {
emit({
sorting: this.popularity * -1,
product_id: this._id,
popularity: this.popularity,
}, 1);
},
'reduce': function(key, values) {
var sum = 0;
values.forEach(function(v) {
sum += v;
});
return sum;
},
'query': {category_id: 20},
'out': {inline: 1},
});
I to jest efekt końcowy (bardzo długo go tutaj wklejać):
http://cesarodas.com/results.txt
To działa, ponieważ teraz sortujemy według sorting, product_id, popularity
. Możesz bawić się sortowaniem, jak tylko chcesz, pamiętaj tylko, że ostateczne sortowanie odbywa się według key
niezależnie od Ciebie, jak posortowane są Twoje dane wejściowe.
W każdym razie, jak powiedziałem wcześniej, powinieneś unikać wykonywania zapytań z Map/Reduce, został zaprojektowany do przetwarzania w tle. Gdybym był tobą, zaprojektowałbym moje dane w taki sposób, abym mógł uzyskać do nich dostęp za pomocą prostych zapytań, w tym przypadku zawsze jest kompromis w przypadku złożonych wstawek/aktualizacji, aby mieć proste zapytania (tak widzę MongoDB).