Prima di tutto, Mongo map/reduce non è progettato per essere utilizzato come strumento di query (come in CouchDB), è progettato per eseguire attività in background. Lo uso al lavoro per analizzare i dati sul traffico.
Quello che stai sbagliando, tuttavia, è che stai applicando sort() al tuo input, ma è inutile perché quando map()
fase è fatto i documenti intermedi sono ordinati per ogni keys
. Poiché la tua chiave è un documento, viene ordinata per product_id
, popularity
.
È così che ho generato il mio set di dati
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)
})
}
}
E questo è il mio compito di mappare/ridurre:
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},
});
E questo è il risultato finale (molto lungo per incollarlo qui):
http://cesarodas.com/results.txt
Funziona perché ora stiamo ordinando per sorting, product_id, popularity
. Puoi giocare con l'ordinamento come preferisci, ricorda solo che l'ordinamento finale è per key
indipendentemente da come è ordinato il tuo input.
Ad ogni modo, come ho detto prima, dovresti evitare di fare query con Map/Reduce, è stato progettato per l'elaborazione in background. Se fossi in te, progetterei i miei dati in modo tale da potervi accedere con query semplici, c'è sempre un compromesso in questo caso inserimenti/aggiornamenti complessi per avere query semplici (è così che vedo MongoDB).