【问题标题】:Most efficient way to generate a list of Unigrams from a text field in MongoDB从 MongoDB 中的文本字段生成 Unigram 列表的最有效方法
【发布时间】:2011-11-01 19:58:41
【问题描述】:

我需要生成一个 unigrams 向量,即出现在特定文本字段中的所有唯一单词的向量,我已将其存储为 MongoDB 中更广泛的 JSON 对象的一部分。

我不确定生成此向量的最简单和最有效的方法是什么。我正在考虑编写一个简单的 Java 应用程序来处理标记化(使用类似 OpenNLP 的东西),但是我认为更好的方法可能是尝试使用 Mongo 的 Map-Reduce 功能来解决这个问题......但是我不是真的确定我该怎么做。

另一种选择是使用 Apache Lucene 索引,但这意味着我仍然需要一个一个地导出这些数据。这与使用自定义 Java 或 Ruby 方法时遇到的问题完全相同......

Map reduce 听起来不错,但是随着更多文档的插入,Mongo 数据每天都在增长。这并不是一项真正的一次性任务,因为一直在添加新文档。更新非常罕见。我真的不想每次我想更新我的 Unigram 矢量时对数百万个文档运行 Map-Reduce,因为我担心这会非常低效地使用资源......

生成一元向量然后保持更新的最有效方法是什么?

谢谢!

【问题讨论】:

    标签: mongodb lucene nlp mapreduce opennlp


    【解决方案1】:

    由于您没有提供示例文档(对象)格式,请将其作为一个名为 'stories' 的示例集合。

    { "_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 代码来获取您的解决方案。集合“authors_unigrams”包含结果。所有代码都应该使用 mongo 控制台 (http://www.mongodb.org/display/DOCS/mongo+-+The+Interactive+Shell) 运行。

    首先,我们需要标记所有重新进入 'stories' 集合的新文档。我们使用以下命令执行此操作。它将在每个文档中添加一个名为“mr_status”的新属性并分配值“inprocess”。稍后,我们将看到 map-reduce 操作只会考虑那些字段“mr_status”的值为“inprocess”的文档。这样,我们可以避免重新考虑之前任何尝试中已经考虑过的 map-reduce 操作的所有文档,从而使操作按要求高效。

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

    第二,我们同时定义了ma​​p()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};
    };
    

    第三,我们实际运行map-reduce函数。

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

    第四,我们通过将“mr_status”设置为“已处理”,将上次运行中考虑进行map-reduce的所有记录标记为已处理。

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

    可选,您可以通过触发以下命令查看结果集合“authors_unigrams”

    db.authors_unigrams.find();
    

    【讨论】:

      猜你喜欢
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多