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
.
Ответы
Ответ 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);
Ответ 4
Только карта без сокращения похожа на копирование коллекции: http://www.mongodb.org/display/DOCS/Developer+FAQ#DeveloperFAQ-HowdoIcopyallobjectsfromonedatabasecollectiontoanother%3F
Ответ 5
Я столкнулся с такой же ситуацией. Я смог выполнить это через запрос и прогнозы Монго. см. Mongo Query