Detta liknar en fråga som ställdes på MongoDB-användares Google-grupper.
https://groups.google.com/group/mongodb-user/browse_thread/thread/60a8b683e2626ada?pli=1
Svaret refererar till en onlinehandledning som liknar ditt exempel:http://tebros.com/2011/07/using-mongodb-mapreduce-to-join-2-collections/
För mer information om MapReduce i MongoDB, se dokumentationen:http://www.mongodb.org/display/DOCS/MapReduce
Dessutom finns det en användbar steg-för-steg-genomgång av hur en MapReduce-operation fungerar i avsnittet "Extras" i MongoDB Cookbook-artikeln med titeln "Finding Max And Min Values with Versioned Documents":http://cookbook.mongodb. org/patterns/finding_max_and_min/
Ursäkta mig om du redan har läst några av de refererade dokumenten. Jag har inkluderat dem till förmån för andra användare som kanske läser det här inlägget och som är nya med att använda MapReduce i MongoDB
Det är viktigt att utdata från 'emit'-satserna i Map-funktionerna matchar utdata från Reduce-funktionen. Om det bara finns ett dokument som matas ut av kartfunktionen, kanske funktionen Reducera inte körs alls, och då kommer din utdatasamling att ha felaktiga dokument.
Jag har ändrat dina kartsatser något för att skicka ut dokument i formatet för önskad utdata, med två separata "klasser"-matriser.
Jag har också omarbetat din reducera-sats för att lägga till nya klasser till classes_1- och classes_2-matriserna, endast om de finns inte redan.
var mapDetails = function(){
var output = {studentid: this.studentid, classes_1: [], classes_2: [], year: this.year, overall: 0, subscore: 0}
if (this.year == 1) {
output.classes_1 = this.classes;
}
if (this.year == 2) {
output.classes_2 = this.classes;
}
emit(this.studentid, output);
};
var mapGpas = function() {
emit(this.studentid, {studentid: this.studentid, classes_1: [], classes_2: [], year: 0, overall: this.overall, subscore: this.subscore});
};
var r = function(key, values) {
var outs = { studentid: "0", classes_1: [], classes_2: [], overall: 0, subscore: 0};
values.forEach(function(v){
outs.studentid = v.studentid;
v.classes_1.forEach(function(class){if(outs.classes_1.indexOf(class)==-1){outs.classes_1.push(class)}})
v.classes_2.forEach(function(class){if(outs.classes_2.indexOf(class)==-1){outs.classes_2.push(class)}})
if (v.year == 0) {
outs.overall = v.overall;
outs.subscore = v.subscore;
}
});
return outs;
};
res = db.details.mapReduce(mapDetails, r, {out: {reduce: 'joined'}})
res = db.gpas.mapReduce(mapGpas, r, {out: {reduce: 'joined'}})
Att köra de två MapReduce-operationerna resulterar i följande samling, som matchar ditt önskade format:
> db.joined.find()
{ "_id" : "12345a", "value" : { "studentid" : "12345a", "classes_1" : [ 1, 17, 19, 21 ], "classes_2" : [ 32, 91, 101, 217 ], "overall" : 97, "subscore" : 1 } }
{ "_id" : "24680a", "value" : { "studentid" : "24680a", "classes_1" : [ 1, 11, 18, 22 ], "classes_2" : [ ], "overall" : 76, "subscore" : 2 } }
{ "_id" : "98765a", "value" : { "studentid" : "98765a", "classes_1" : [ 2, 12, 19, 22 ], "classes_2" : [ 32, 99, 110, 215 ], "overall" : 85, "subscore" : 5 } }
>
MapReduce matar alltid ut dokument i form av {_id:"id", värde:"value"}Det finns mer information tillgänglig om att arbeta med underdokument i dokumentet med titeln "Dot Notation (Reaching into Objects)":http:/ /www.mongodb.org/display/DOCS/Dot+Notation+%28Reaching+into+Objects%29
Om du vill att utdata från MapReduce ska visas i ett annat format måste du göra det programmatiskt i din applikation.
Förhoppningsvis kommer detta att förbättra din förståelse av MapReduce och ta dig ett steg närmare att producera din önskade utdatasamling. Lycka till!