Я пытался свести много больших наборов данных в одну коллекцию, но у меня возникают проблемы при написании функции MapReduce, чтобы туда попасть.
Вот как выглядят мои данные (вот17 строк, на самом деле у меня 4+ миллиона):
{"user": 1, "day": 1, "type": "a", "sum": 10}
{"user": 1, "day": 2, "type": "a", "sum": 32}
{"user": 1, "day": 1, "type": "b", "sum": 11}
{"user": 2, "day": 4, "type": "b", "sum": 2}
{"user": 1, "day": 2, "type": "b", "sum": 1}
{"user": 1, "day": 3, "type": "b", "sum": 9}
{"user": 1, "day": 4, "type": "b", "sum": 12}
{"user": 2, "day": 2, "type": "a", "sum": 3}
{"user": 3, "day": 2, "type": "b", "sum": 81}
{"user": 1, "day": 4, "type": "a", "sum": 22}
{"user": 1, "day": 5, "type": "a", "sum": 39}
{"user": 2, "day": 5, "type": "a", "sum": 8}
{"user": 2, "day": 3, "type": "b", "sum": 1}
{"user": 3, "day": 3, "type": "b", "sum": 99}
{"user": 2, "day": 3, "type": "a", "sum": 5}
{"user": 1, "day": 3, "type": "a", "sum": 41}
{"user": 3, "day": 4, "type": "b", "sum": 106}
...
В конце я пытаюсь, чтобы это выглядело так (массив для каждого типа, где содержимое - это просто суммы всоответствующий индекс, определенный днем, если этот день не существует для этого типа, это просто 0):
{"user": 1, "type_a_sums": [10, 32, 41, 22, 39], "type_b_sums": [11, 1, 9, 12, 0]}
{"user": 2, "type_a_sums": [0, 3, 5, 0, 8], "type_b_sums": [0, 0, 1, 2, 0]}
{"user": 3, "type_a_sums": [0, 0, 0, 0, 0], "type_b_sums": [0, 81, 99, 106, 0]}
...
Это MapReduce, который я пробовал:
var mapsum = function(){
var output = {user: this.user, type_a_sums: [0, 0, 0, 0, 0], type_b_sums: [0, 0, 0, 0, 0], tempType: this.type, tempSum: this.sum, tempDay: this.day}
if(this.type == "a") {
output.type_a_sums[this.day-1] = this.sum;
}
if(this.type == "b") {
output.type_b_sums[this.day-1] = this.sum;
}
emit(this.user, output);
};
var r = function(key, values) {
var outs = {user: 0, type_a_sums: [0, 0, 0, 0, 0], type_b_sums: [0, 0, 0, 0, 0], tempType: -1, tempSum: -1, tempDay: -1}
values.forEach(function(v){
outs.user = v.user;
if(v.tempType == "a") {
outs.type_a_sums[v.tempDay-1] = v.tempSum;
}
if(v.tempType == "b") {
outs.type_b_sums[v.tempDay-1] = v.tempSum;
}
});
return outs;
};
res = db.sums.mapReduce(mapsum, r, {out: 'joined_sums'})
Это дает мне вывод на небольшой выборке, но когда я запускаю его на все 4 миллиона, я получаю тонну выводов, которые выглядят так:
{"user": 1, "type_a_sums": [0, 0, 0, 0, 0], "type_b_sums": [0, 0, 0, 0, 0]}
{"user": 2, "type_a_sums": [0, 3, 5, 0, 8], "type_b_sums": [0, 0, 1, 2, 0]}
{"user": 3, "type_a_sums": [0, 0, 0, 0, 0], "type_b_sums": [0, 0, 0, 0, 0]}
Где большая часть users
, которая должнау сумм в их массивах фактически просто заполняются нулями, которые были в фиктивном массиве в объекте reduce
functions outs
, прежде чем я заполняю его фактической функцией.
Что действительно странно, если язапустить ту же самую функцию на том же соllection, но проверьте только для одного пользователя res = db.sums.mapReduce(mapsum, r, {query: {user: 1}, out: 'joined_sums'})
, который, как я знаю, должен иметь суммы в своих массивах, но ранее он показывал все 0, на самом деле я получу вывод, который хотел получить только для этого пользователя.Запустите его снова через все 4 миллиона, и я снова вернусь к нулю.Как будто он просто переписывает всю работу, которую он проделал с фиктивными массивами-заполнителями.
У меня слишком много данных?Разве это не должно быть в состоянии пройти через это, учитывая время?Или я бью какой-то барьер, о котором я не знаю?