mongoDb全局(范围)变量在多碎片安装上的使用



我正在设计一个能够处理数百万文档并以不同方式报告它们的系统。mongoDb map\reduce任务是我试图实现的(目前正在对此进行一些调查)。最基本的文档结构是

db.test.insert(
{
        "_id" : ObjectId("4f6063601caf46303c36eb27"),
        "verbId" : NumberLong(1506281),
        "sentences" : [
                {
                        "sId" : NumberLong(2446630),
                        "sentiment" : 2,
                        "categories" : [
                                NumberLong(3257),
                                NumberLong(3221),
                                NumberLong(3291)
                        ]
                },
                {
                        "sId" : NumberLong(2446631),
                        "sentiment" : 0,
                        "categories" : [
                                NumberLong(2785),
                                NumberLong(2762),
                                NumberLong(2928),
                                NumberLong(2952)
                        ]
                },
                {
                        "sId" : NumberLong(2446632),
                        "sentiment" : 0,
                        "categories" : [
                                NumberLong(-2393)
                        ]
                },
                {
                        "sId" : NumberLong(2446633),
                        "sentiment" : 0,
                        "categories" : [
                                NumberLong(-2393)
                        ]
                }
        ]
})

因此,每个文档都包含可以属于不同类别的句子。我想得到的报告是类别中的句子数量(动词的百分比)。

我正在用finalize方法计算不同的平均值来做下一个地图减少作业。

var map = function() {
        var docCategories = new Array();
        var catValues = new Array();
        for (var i = 0; i < this.sentences.length; i++) { //iterate over sentences.
            sentence = this.sentences[i];
            for (var j = 0; j < sentence.categories.length; j++) {//iterate over categories
                catId= sentence.categories[j].toNumber();
                if (docCategories.indexOf(catId) < 0) {
                    docCategories.push(catId);
                    catValues.push({sentiment : sentence.sentiment, sentenceCnt: 1});
                } else {
                    categoryIdx = docCategories.indexOf(catId);
                    catValue = catValues[categoryIdx];
                    catValue.sentiment = catValue.sentiment + sentence.sentiment;
                    catValue.sentenceCnt = catValue.sentenceCnt + 1;
                }
            }
        }
        totalCount++; //here we do try to count distinctCases see scope.
        for (var i = 0; i < docCategories.length; i ++) {
            emit(docCategories[i], {count: 1, sentenceCnt: catValues[i].sentenceCnt, sentiment: catValues[i].sentiment, totalCnt : totalCount});
        }
    };
var reduce = function(key, values) {
    var res = {count : 0, sentenceCnt : 0, sentiment : 0};
    for ( var i = 0; i < values.length; i ++ ) {
        res.count += values[i].count;
        res.sentenceCnt += values[i].sentenceCnt;
        res.sentiment += values[i].sentiment;
    }
    return res;
};
var finalize = function(category, values) {
    values.sentimentAvg = values.sentiment / values.sentenceCnt; 
    values.percentOfVerbatim = values.count / totalCount //scope variable (global)
    return values;
};

var res = db.runCommand( { mapreduce:'test',
                  map:map,
                  reduce:reduce,
                  out: 'cat_volume',
                  finalize:finalize,
                  scope:{totalCount : 0},
                });

这里最有趣的部分是我使用totalCount来计算我发出的动词数量。totalCount是scope(全局)变量。One mongoDb安装时一切都很顺利,但当使用shard实例时,我得到了percentOfVerbatim的"无限"。

事实上,在这种情况下,totalCount将只是db.test.count()(文档数),但在未来,我将为要计数的文档添加不同的条件。执行任何其他查询都是非常不可取的,因为数据库非常重。

有没有其他方法可以在多实例mongodb安装中使用全局(范围)变量?或者我应该用别的东西吗?

作用域变量不是在碎片之间共享的。你可以把它看作一个全局常数。该值的更新对于映射或减少在不同碎片上运行的函数是不可见的。

最后我找到了如何计算我发出的文档数的方法。对我来说,唯一有效的方法是发出documentId,并在reduce上将id放入数组中。在客户端(我正在编写java程序),我必须计算所有不同的Id。所以,在做地图的时候,我确实会发射

emit(docCategories[i], {verbIds : [this.verbId.toNumber()], count: 1, sentenceCnt: catValues[i].sentenceCnt, sentiment: catValues[i].sentiment, totalCnt : totalCount});

减少功能如下:

var reduce = function(key, values) {
    var res = {verbIds : [], count : 0, sentenceCnt : 0, sentiment : 0};
    for ( var i = 0; i < values.length; i ++ ) {
//      res.verbIds = res.verbIds.concat(values[i].verbIds); //works slow
        for ( var j = 0; j < values[i].verbIds.length; j ++ ) {
            res.verbIds.push(values[i].verbIds[j]);
        }
        res.count += values[i].count;
        res.sentenceCnt += values[i].sentenceCnt;
        res.sentiment += values[i].sentiment;
    }
    return res;
};

Java端程序只计算所有结果的不同Id。

实际上,对于110万份文档,的执行速度显著减慢

相关内容

  • 没有找到相关文章

最新更新