Подтвердить что ты не робот

MongoDB карта/уменьшить минус сокращение

У меня есть около 25 тыс. документов (4 ГБ в сыром json) данных, которые я хочу выполнить для нескольких javascript-операций, чтобы сделать его более доступным для моего конечного пользователя данных (R), и я хотел бы "контроль версий" этих изменений, добавив новую коллекцию для каждого изменения, но я не могу понять, как map/reduce без reduce. Я хочу создать сопоставление документов один к одному - я начинаю с 25 356 документов в collection_1, и я хочу получить 25 356 документов в collection_2.

Я могу взломать это с помощью этого:

var reducer = function(key, value_array) {
    return {key: value_array[0]}
}

И затем назовите его так:

db.flat_1.mapReduce(mapper, reducer, {keeptemp: true, out: 'flat_2'})

(Мой картограф только вызывает emit один раз, строка как первый аргумент, а заключительный документ - второй. Это набор тех вторых аргументов, которые я действительно хочу.)

Но это кажется неудобным, и я не знаю, почему он даже работает, поскольку мои аргументы вызова emit в моем модуле сопоставления не эквивалентны возвращаемому аргументу моего reducer. Кроме того, я получаю документ вроде

{
    "_id": "0xWH4T3V3R", 
    "value": {
        "key": {
            "finally": ["here"],
            "thisIsWhatIWanted": ["Yes!"]
        }
    }
}

который кажется лишним.

Кроме того, курсор, который выполняет свои собственные вставки, даже не десятый, как mapReduce. Я не знаю MongoDB достаточно хорошо, чтобы сравнить его, но я бы догадался о 50x медленнее. Есть ли способ запустить курсор параллельно? Мне все равно, если документы в моем collection_2 находятся в другом порядке, чем в collection_1.

4b9b3361

Ответ 1

При использовании map/reduce вы всегда будете

{ "value" : { <reduced data> } }

Чтобы удалить ключ value, вам нужно будет использовать функцию finalize.

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

map = function() { emit(this._id, this ); }
reduce = function(key, values) { return values[0]; }
finalize = function(key, value) { db.collection_2.insert(value); }

Затем, когда вы будете работать как обычно:

db.collection_1.mapReduce(map, reduce, { finalize: finalize });

Ответ 2

Но это кажется неудобным, и я не знаю, почему он даже работает, поскольку мои аргументы вызова emit в моем модуле сопоставления не эквивалентны возвращаемому аргументу моего reducer.

Они эквивалентны. Функция уменьшения принимает массив значений T и должна возвращать одно значение в том же формате T. Формат T определяется вашей функцией отображения. Функция сокращения просто возвращает первый элемент в массиве значений, который всегда будет иметь тип T. Вот почему он работает:)

Ты, кажется, на правильном пути. Я экспериментировал, и, похоже, вы не можете сделать db.collection.save() из функции карты, но вы можете сделать это из функции уменьшения. Ваша функция карты должна просто создать необходимый формат документа:

function map() {
  emit(this._id, { _id: this.id, heading: this.title, body: this.content });
}

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

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

function reduce(key, values) {
  db.result.save(values[0]);

  return null;
}

Теперь db.result должен содержать преобразованные документы, без каких-либо дополнительных шумов, уменьшающих размер карты, которые вы имели бы во временной коллекции. Я на самом деле не тестировал это на больших объемах данных, но этот подход должен использовать преимущества параллельного выполнения функций уменьшения карты.

Ответ 3

Когда вы получили доступ к оболочке mongo, он принимает некоторые команды Javascript, а затем проще:

map = function(item){
        db.result.insert(item);
}

db.collection.find().forEach(map);

Ответ 5

Я столкнулся с такой же ситуацией. Я смог выполнить это через запрос и прогнозы Монго. см. Mongo Query