MapReduce zou een goede oplossing kunnen zijn die de documenten op de server kan verwerken zonder de client te manipuleren (omdat er geen functie is om een string op de DB-server te splitsen (open probleem).
Begin met de map
functie. In het onderstaande voorbeeld (dat waarschijnlijk robuuster moet zijn), wordt elk document doorgegeven aan de map
functie (zoals this
). De code zoekt naar de summary
veld en als het daar is, kleine letters, splitst op een spatie, en zendt dan een 1
uit voor elk gevonden woord.
var map = function() {
var summary = this.summary;
if (summary) {
// quick lowercase to normalize per your requirements
summary = summary.toLowerCase().split(" ");
for (var i = summary.length - 1; i >= 0; i--) {
// might want to remove punctuation, etc. here
if (summary[i]) { // make sure there's something
emit(summary[i], 1); // store a 1 for each word
}
}
}
};
Dan, in de reduce
functie, somt het alle resultaten op die zijn gevonden door de map
functie en geeft een discreet totaal terug voor elk woord dat emit
. was ted hierboven.
var reduce = function( key, values ) {
var count = 0;
values.forEach(function(v) {
count +=v;
});
return count;
}
Voer ten slotte de mapReduce uit:
> db.so.mapReduce(map, reduce, {out: "word_count"})
De resultaten met uw voorbeeldgegevens:
> db.word_count.find().sort({value:-1})
{ "_id" : "is", "value" : 3 }
{ "_id" : "bad", "value" : 2 }
{ "_id" : "good", "value" : 2 }
{ "_id" : "this", "value" : 2 }
{ "_id" : "neither", "value" : 1 }
{ "_id" : "or", "value" : 1 }
{ "_id" : "something", "value" : 1 }
{ "_id" : "that", "value" : 1 }