MongoDB MapReduce странное значение, когда функция limit не использует переменную из emit - PullRequest
2 голосов
/ 01 марта 2012

Я хочу использовать mapreduce для агрегирования групп. Вот моя функция карты:

function() {
     emit(this.TransactionType, { Count: 1 });
}

Вот две функции уменьшения:

function(key, values) {
    var result = {Count: 0};
    values.forEach(function(value) {
        result.Count += 1; 
    });
    return result;
}

function(key, values) {
    var result = {Count: 0};
    values.forEach(function(value) {
        result.Count += value.Count; 
    });
    return result;
}

и вот два результата:

"_id" : "A", "value" : { "Count" : 13.0 }  
"_id" : "B", "value" : { "Count" : 2.0 }  
"_id" : "C", "value" : { "Count" : 1.0 }  
"_id" : "D", "value" : { "Count" : 209.0 }  
"_id" : "E", "value" : { "Count" : 66.0 }  
"_id" : "F", "value" : { "Count" : 11.0 }  
"_id" : "G", "value" : { "Count" : 17.0 }  
"_id" : "H", "value" : { "Count" : 17.0 } 


"_id" : "A", "value" : { "Count" : 128.0 } 
"_id" : "B", "value" : { "Count" : 115.0 } 
"_id" : "C", "value" : { "Count" : 1.0 } 
"_id" : "D", "value" : { "Count" : 3645.0 } 
"_id" : "E", "value" : { "Count" : 1405.0 } 
"_id" : "F", "value" : { "Count" : 256.0 } 
"_id" : "G", "value" : { "Count" : 380.0 } 
"_id" : "H", "value" : { "Count" : 398.0 } 

Так почему же два результата отличаются?

Большое спасибо

Ответы [ 3 ]

1 голос
/ 01 марта 2012

Функция приведения должна быть написана так, чтобы ее можно было повторно запустить несколько раз, используя ее собственный вывод в качестве нового ввода.

Функция результата выводит данные в виде {_id, [values]}.Для вашей функции сокращения входные данные могут быть следующими:

"A", [{count:1}, {count:2}, {count:3}]

В первой функции число будет увеличиваться только на 1 для каждого документа в массиве значений, и на выходе будет:

"A", {count:3}

во второй функции, значения счетчика будут добавлены, поэтому на выходе будет

"A", {count:6}

Это то, что вы испытываете.Пошаговое руководство по выполнению операции Map Reduce см. В разделе «Дополнительно» рецепта поваренной книги MongoDB «Поиск максимальных и минимальных значений с версионными документами» http://cookbook.mongodb.org/patterns/finding_max_and_min/

удачии счастливого сокращения карт!

1 голос
/ 01 марта 2012

Первая функция уменьшения делает это для каждого значения:

result.Count += 1; 

Второй делает это:

result.Count += value.Count;

Итак, если ваш список значений равен (1,2,3,4,5), первый из них добавит +1 для каждого элемента и вернет 5 в качестве выходных данных. Второй добавит +5 к каждому элементу (потому что value.Count равен 5), и поэтому будет выводить 5 + 5 + 5 + 5 + 5 = 25

0 голосов
/ 01 марта 2012

Полезно думать о функции «уменьшить» в терминах «кратной» функции высшего порядка . Другими словами, ваша функция «Reduce» будет применена к списку значений и к накопленному объекту (переменная «result» в ваших примерах), который изначально указан, но в конечном итоге будет заменен вывод последовательных вызовов вашей функции . Более того, список значений, к которым будет применяться ваша функция, можно разбить на любое количество подсписков в любом порядке!

Например, рассмотрим, как ваша функция будет вести себя, используя JavaScript Array «Reduce» функцию , которая является примером функции «fold» высшего порядка. Ваш первый пример будет работать неправильно, потому что он не использует свойство «Count» каждого элемента. Последующие попытки использовать его с Array # redund также потерпят неудачу:

function badReducer(accum, x) {
  accum.Count += 1;
  return accum;
}
var sum = {Count:0};
sum = [{Count:1}, {Count:2}, {Count:3}].reduce(badReducer, sum);
sum; // => {Count:3}, d'oh!
sum = [{Count:4}].reduce(badReducer, sum);
sum; // => {Count:5}, d'oh!

Однако ваш второй пример правильно добавляет свойство «Количество» и может последовательно применяться к своему собственному выводу:

function goodReducer(accum, x) {
  accum.Count += x.Count;
  return accum;
}
var sum = {Count:0};
sum = [{Count:1}, {Count:2}, {Count:3}].reduce(goodReducer, sum);
sum; // => {Count:6}, woohoo!
sum = [{Count:4}].reduce(goodReducer, sum);
sum; // => {Count:10}, woohoo!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...