MongoDB отобразить / уменьшить на несколько коллекций? - PullRequest
16 голосов
/ 01 октября 2010

Во-первых, фон.Я имел обыкновение иметь коллекцию logs и использовал карту / уменьшение для создания различных отчетов.Большинство этих отчетов были основаны на данных за один день, поэтому у меня всегда было условие d: SOME_DATE.Когда коллекция logs стала чрезвычайно большой, вставка стала чрезвычайно медленной (медленнее, чем приложение, которое мы отслеживали, генерировало журналы), даже после удаления большого количества индексов.Поэтому мы решили хранить данные за каждый день в отдельной коллекции - logs_YYYY-mm-dd - таким образом, индексы будут меньше, и нам даже не нужен индекс на дату.Это круто, так как большинство отчетов (таким образом, отображают / уменьшают) на ежедневных данных.Однако у нас есть отчет, в котором мы должны охватить несколько дней.

А теперь вопрос.Есть ли способ запустить карту / уменьшить (или, точнее, карту) для нескольких коллекций, как если бы она была только одна?

Ответы [ 2 ]

35 голосов
/ 01 октября 2010

Функция приведения может быть вызвана один раз, с ключом и всеми соответствующими значениями (но только при наличии нескольких значений для ключа - она ​​не будет вызываться вообще, если есть только 1 значение для ключ).

Он также может вызываться несколько раз, каждый раз с ключом и только подмножеством соответствующих значений , и предыдущий результат уменьшения для этого ключа. Этот сценарий называется повторным сокращением . Для поддержки повторного сокращения ваша функция уменьшения должна быть идемпотентной .

В идемпотентной функции уменьшения есть две ключевые особенности:

  • Возвращаемое значение функции Reduce должно быть в том же формате , что и значения , которые она принимает. Так что, если ваша функция Reduce принимает массив строк, функция должна вернуть строку. Если он принимает объекты с несколькими свойствами, он должен возвращать объект, содержащий те же свойства. Это гарантирует, что функция не прервется при вызове с результатом предыдущего сокращения.
  • Не делайте предположений, основываясь на количестве значений , которое он принимает. Не гарантируется, что параметр values содержит все значения для данного ключа. Поэтому использование values.length в расчетах очень рискованно, и его следует избегать.

Обновление: Два последних шага не являются обязательными (или даже невозможными, я не проверял) в последних версиях MongoDB. Теперь он может обработать эти шаги для вас, если вы укажете выходную коллекцию в map-limit options :

{ out: { reduce: "tempResult" } }

Если ваша функция сокращения идемпотентна, у вас не должно возникнуть проблем с уменьшением карты нескольких коллекций. Просто уменьшите результаты каждой коллекции:

Шаг 1

Запустите map-reduction для каждой требуемой коллекции и сохраните результаты в одной временной коллекции. Вы можете сохранить результаты, используя функцию финализации :

finalize = function (key, value) {
  db.tempResult.save({ _id: key, value: value });
}

db.someCollection.mapReduce(map, reduce, { finalize: finalize })
db.anotherCollection.mapReduce(map, reduce, { finalize: finalize })

Шаг 2

Запустите другую карту-уменьшение для временной коллекции, , используя ту же функцию уменьшения . Функция map - это простая функция, которая выбирает ключи и значения из временной коллекции:

map = function () {
  emit(this._id, this.value);
}

db.tempResult.mapReduce(map, reduce)

Это второе уменьшение карты, по сути, является повторным уменьшением и должно дать вам необходимые результаты.

1 голос
/ 02 декабря 2017

Я использовал map-reduce метод.Вот пример.

var mapemployee = function () {
    emit(this.jobid,this.Name);};

var mapdesignation = function () {
    emit(this.jobid, this.Designation);};

var reduceF = function(key, values) {
    var outs = {Name:null,Designation: null};
    values.forEach(function(v){
    if(outs.Name ==null){
   outs.Name = v.Name }
   if(outs.Name ==null){
    outs.Nesignation = v.Designation}                    
     });
    return outs;
};

result = db.employee.mapReduce(mapemployee, reduceF, {out: {reduce: 'output'}});
result = db.designation.mapReduce(mapdesignation,reduceF, {out: {reduce: 'output'}});

Ссылка: http://www.itgo.me/a/x3559868501286872152/mongodb-join-two-collections

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...