Това е подобно на въпрос, зададен в Google Groups за потребители на MongoDB.
https://groups.google.com/group/mongodb-user/browse_thread/thread/60a8b683e2626ada?pli=1
Отговорът препраща към онлайн урок, който изглежда подобен на вашия пример:http://tebros.com/2011/07/using-mongodb-mapreduce-to-join-2-collections/
За повече информация относно MapReduce в MongoDB, моля, вижте документацията:http://www.mongodb.org/display/DOCS/MapReduce
Освен това, има полезна стъпка по стъпка как работи операцията MapReduce в секцията „Екстри“ на статията в MongoDB Cookbook, озаглавена „Намиране на максимални и минимални стойности с версии на документи“:http://cookbook.mongodb. org/patterns/finding_max_and_min/
Извинете ме, ако вече сте прочели някои от посочените документи. Включих ги в полза на други потребители, които може би четат тази публикация и са нови в използването на MapReduce в MongoDB
Важно е изходите от операторите 'emit' във функциите Map да съвпадат с изходите на функцията Reduce. Ако има само един документ, изведен от функцията Map, функцията Reduce може изобщо да не се изпълнява и тогава вашата изходна колекция ще има несъответстващи документи.
Промених леко вашите изрази за карта, за да излъчват документи във формата на желания от вас изход, с два отделни масива "класове".
Преработих също така вашия израз за намаляване, за да добавя нови класове към масивите classes_1 и classes_2, само ако те вече не съществуват.
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'}})
Изпълнението на двете операции MapReduce води до следната колекция, която съответства на желания от вас формат:
> 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 винаги извежда документи под формата на {_id:"id", value:"value"}Има повече информация за работа с поддокументи в документа, озаглавен "Точкова нотация (достигане до обекти)":http:/ /www.mongodb.org/display/DOCS/Dot+Notation+%28Reaching+into+Objects%29
Ако искате изходът на MapReduce да се показва в различен формат, ще трябва да направите това програмно във вашето приложение.
Надяваме се, че това ще подобри разбирането ви за MapReduce и ще ви приближи една крачка по-близо до създаването на желаната от вас колекция. Успех!