2016-10-16 5 views
0

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

Мы должны собрать fill-rates этих полей, мы написали скрипт, который обрабатывает все документы и подсчитывает значения заполнения для каждого, проблема в том, что обработка всех документов занимает много времени.

Есть ли способ использовать db.collection.aggregate или db.collection.mapReduce для запуска такого скриптового сервера? Должны ли они иметь значительные улучшения в производительности? Будет ли это замедлять другие способы использования этой коллекции (например, проведение крупного замка)?

ответ

1

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

Вот как старый скрипт работал (в node.js):

var cursor = collection.find(query, projection).sort({_id: 1}).limit(limit); 
var next = function() { 
    cursor.nextObject(function(err, doc) { 
     processDoc(doc, next); 
    }); 
}; 
next(); 

и это новый сценарий:

collection.mapReduce(
    function() { 
     var processDoc = function(doc) { 
      ... 
     }; 
     processDoc(this); 
    }, 
    function (key, values) { 
     return Array.sum(values) 
    }, 
    { 
     query : query, 
     out: {inline: 1} 
    }, 
    function (error, results) { 
     // print results 
    } 
); 

processDoc остались в основном те же, но вместо того, чтобы инкремент счетчика на объект глобальная статистика, я:

emit(field_name, 1); 

работает старо го нового на образце 100k, старый потребовалось 20 секунд, новый взял 8.

некоторые примечания:

  1. карта-свертка-х limit опция не работает на sharded коллекции, я должен был запросить для _id : { $gte, $lte}, чтобы создать необходимый размер выборки.
  2. Функция повышения производительности карты-уменьшения: jsMode : true также не работает с оштукатуренными коллекциями (возможно, еще больше повышает производительность), это может работать, чтобы запускать ее вручную на каждом осколке, чтобы получить эту функцию.
+0

Все еще ваш вопрос непонятен, вы не говорите, если Aggregate быстрее, чем MapReduce. Во всяком случае хорошая работа! –

+0

На самом деле я не знаю, потому что не смог найти общий способ миграции из простого скрипта node.js, который обрабатывает документы один за другим с помощью агрегатной функции, описанное выше решение описывает, как я мог это сделать с помощью map- уменьшить – marmor

1

Как я понял, что вы хотите достичь, это вычислить что-то на ваших документах, после чего у вас есть новый «документ», который можно запросить. Вам не нужно запоминать «новые значения».

Если вам не нужно писать свои «новые значения» внутри этих документов, вы можете использовать Агрегационную структуру.

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

https://docs.mongodb.com/manual/aggregation/

Поскольку Aggregation Framework имеет много особенностей, я не могу дать вам больше информации о том, как решить проблему.

+0

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

+0

, пожалуйста, обновите свой вопрос с данными, которые у вас есть в коллекции. –

+0

спасибо, мне удалось переписать мой скрипт с помощью map-reduce, см. Мой ответ ниже. – marmor