【问题标题】:MongoDB javascript pass argumentMongoDB javascript 传递参数
【发布时间】:2012-11-19 15:25:26
【问题描述】:

我有一个关于将 MongoDB javascript 中的参数传递给 map 函数的问题。 目前,我的想法是这样的:

var map = function(n) {
    if(this.x == n){
        emit(this.x);
    }
}
var reduce = function(key, values) {
    values.forEach(function(x) {
        //do something
    });
    return {nd:values};
}
db.smsdb.mapReduce(map(2), reduce, "collection")

但是当我试图这样做时,shell 返回一个错误“不是代码”......所以我猜我没有以正确的方式这样做。 有没有人对这类问题有正确的解决方案,我很高兴能把它做对。

谢谢

【问题讨论】:

    标签: javascript mongodb map arguments reduce


    【解决方案1】:

    Mapreduce 中的范围代表 Map Reduce 中的全局参数 正如@Dave Griffith 所指出的,您可以使用mapReduce 函数的范围参数。

    我很难弄清楚如何正确地将它传递给函数,因为正如其他人所指出的那样,文档不是很详细。最后,我意识到mapReduce 需要 3 个参数:

    map function
    reduce function
    object with one or more of the params defined in the doc
    Eventually, I arrived at the following code in Javascript:
    
    // I define a variable external to my map and to my reduce functions
    var KEYS = {STATS: "stats"};
    
    function m() {
        // I use my global variable inside the map function
        emit(KEYS.STATS, 1);
    }
    
    function r(key, values) {
        // I use a helper function
        return sumValues(values);
    }
    
    // Helper function in the global scope
    function sumValues(values) {
        var result = 0;
        values.forEach(function(value) {
            result += value;
        });
        return value;
    }
    
    db.something.mapReduce(
        m,
        r,
        {
             out: {inline: 1},
             // I use the scope param to pass in my variables and functions
             scope: {
                 KEYS: 1,
                 sumValues: 22// of course, you can pass function objects too
             }
        }
    );
    

    【讨论】:

      【解决方案2】:

      我还应该指出,这个解决方案也有效:

      var map = function() { if(this.x == n){ emit(this.x); } } db.smsdb.mapReduce(mapper, reduce, {out:"nodes",scope:{n:2}});

      【讨论】:

        【解决方案3】:

        这一行:

        db.smsdb.mapReduce(map(2), reduce, "collection")
        

        正在调用 map(2),结果 (undefined) 作为 mapReduce 的映射函数传递。

        改为执行以下操作:

        db.smsdb.mapReduce(function(){ map.call(this, 2); }, reduce, "collection")
        

        更新

        上述方法不起作用,因为map 函数在mapReduce 映射函数运行的范围内不可用。所以你必须把它包装成一个可以生成你需要的map函数的函数:

        var mapper = function(n) {
            function map() {
                if(this.x == n){
                    emit(this.x);
                }
            }
            return map;
        };
        db.smsdb.mapReduce(mapper(2), reduce, "collection");
        

        【讨论】:

        • 这不返回值...我收到错误参考错误:未定义地图。但是,如果我发出 2 个字段,有什么变化吗?
        • @box 不使用map 函数的返回值,重要的是通过emit 发出的值。您可以根据需要发出任意数量的字段,但发出的对象的形状必须与您的 reduce 函数返回的内容匹配(目前不匹配)。
        • 我不太了解你,你能举个例子吗?请
        • @box 查看修复Reference error:map问题的更新答案。
        【解决方案4】:

        你可以这样做:

        db.smsdb.mapReduce(function() { return map(2); }, reduce, "collection")
        

        【讨论】:

        • 我收到您的代码错误,它说 Refference error:map is not defined。你确定这应该有效吗?
        • 这很奇怪。这绝对应该有效。看起来匿名函数无法访问之前定义的映射函数。 map 函数的范围与您在问题中发布的相同吗?
        • 其实地图是这样的:function map(n){ if(this.src==n){ emit(this.src, this.dst); } }
        • 请注意,决定传递给 map 的内容是由 mapReduce 为您完成的。还是您每次都明确要传递2
        • 2 是一个变量,所以它可以是任何数字
        猜你喜欢
        • 2012-06-16
        • 1970-01-01
        • 2017-10-20
        • 2015-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多