Самый эффективный способ создания списка Unigrams из текстового поля в MongoDB - PullRequest
0 голосов
/ 08 июля 2011

Мне нужно сгенерировать вектор униграмм, то есть вектор всех уникальных слов, которые появляются в определенном текстовом поле, которые я сохранил как часть более широкого объекта JSON в MongoDB.

Яне совсем уверен, что это самый простой и эффективный способ генерации этого вектора.Я думал о написании простого Java-приложения, которое могло бы обрабатывать токенизацию (используя что-то вроде OpenNLP), однако я думаю, что лучшим подходом может быть попытка заняться этим с помощью функции Map-Reduce Монго ... Однако я не совсемуверен, как я мог пойти об этом.

Другой вариант - использовать индексацию Apache Lucene, но это будет означать, что мне все равно придется экспортировать эти данные по одному.Это действительно та же самая проблема, с которой я столкнулся бы с пользовательским подходом Java или Ruby ...

Карта хорошо уменьшает звуки, однако данные Монго растут с каждым днем ​​по мере добавления большего количества документов.На самом деле это не единственная задача, поскольку все время добавляются новые документы.Обновления очень редки.Я действительно не хочу запускать Map-Reduce для миллионов документов каждый раз, когда я хочу обновить свой вектор Unigram, так как боюсь, что это будет очень неэффективным использованием ресурсов ...

Что будетсамый эффективный способ создания вектора униграмм и его обновления?

Спасибо!

1 Ответ

2 голосов
/ 01 ноября 2011

Поскольку вы не предоставили формат образца документа (объекта), примите его в качестве образца коллекции под названием 'story' .

{ "_id" : ObjectId("4eafd693627b738f69f8f1e3"), "body" : "There was a king", "author" : "tom" }
{ "_id" : ObjectId("4eafd69c627b738f69f8f1e4"), "body" : "There was a queen", "author" : "tom" }
{ "_id" : ObjectId("4eafd72c627b738f69f8f1e5"), "body" : "There was a queen", "author" : "tom" }
{ "_id" : ObjectId("4eafd74e627b738f69f8f1e6"), "body" : "There was a jack", "author" : "tom" }
{ "_id" : ObjectId("4eafd785627b738f69f8f1e7"), "body" : "There was a humpty and dumpty . Humtpy was tall . Dumpty was short .", "author" : "jane" }
{ "_id" : ObjectId("4eafd7cc627b738f69f8f1e8"), "body" : "There was a cat called Mini . Mini was clever cat . ", "author" : "jane" }

. Для данного набора данных вы можете использоватьследующий код JavaScript, чтобы добраться до вашего решения.Коллекция " авторы_unigrams " содержит результат.Весь код должен быть запущен с использованием консоли mongo (http://www.mongodb.org/display/DOCS/mongo+-+The+Interactive+Shell).

Сначала , нам нужно пометить все новые документы, которые снова попали в 'story' Мы делаем это, используя следующую команду: он добавит новый атрибут с именем «mr_status» в каждый документ и присвоит значение «inprocess». Позже мы увидим, что операция map-Reduce будет принимать только те документы, которые имеютзначение "inprocess" для поля "mr_status". Таким образом, мы можем избежать повторного рассмотрения всех документов для операции уменьшения карты, которые уже рассматривались в любой из предыдущих попыток, что делает операцию эффективной в соответствии с запросом.

db.stories.update({mr_status:{$exists:false}},{$set:{mr_status:"inprocess"}},false,true);

Второй , мы определяем обе функции map () и Reduce () .

var map = function() {
        uniqueWords = function (words){
            var arrWords = words.split(" ");
            var arrNewWords = [];
            var seenWords = {};
            for(var i=0;i<arrWords.length;i++) {
                if (!seenWords[arrWords[i]]) {
                    seenWords[arrWords[i]]=true;
                    arrNewWords.push(arrWords[i]);
                }
            }
            return arrNewWords;
        }
      var unigrams =  uniqueWords(this.body) ;
      emit(this.author, {unigrams:unigrams});
};

var reduce = function(key,values){

    Array.prototype.uniqueMerge = function( a ) {
        for ( var nonDuplicates = [], i = 0, l = a.length; i<l; ++i ) {
            if ( this.indexOf( a[i] ) === -1 ) {
                nonDuplicates.push( a[i] );
            }
        }
        return this.concat( nonDuplicates )
    };

    unigrams = [];
    values.forEach(function(i){
        unigrams = unigrams.uniqueMerge(i.unigrams);
    });
    return { unigrams:unigrams};
};

Третий , мы фактически запускаем функцию уменьшения карты.

var result  = db.stories.mapReduce( map,
                                  reduce,
                                  {query:{author:{$exists:true},mr_status:"inprocess"},
                                   out: {reduce:"authors_unigrams"}
                                  });

Четвертый , мы помечаем все записи, которые были рассмотрены для уменьшения карты в последнем запуске, как обработанные установкой "mr_status "как" обработано ".

db.stories.update({mr_status:"inprocess"},{$set:{mr_status:"processed"}},false,true);

Опционально , вы можете увидеть коллекцию результатов "hors_unigrams" , запустив следующую команду.

db.authors_unigrams.find();
...