【问题标题】:MongoDB MapReduce scope of higher order functionsMongoDB MapReduce 高阶函数范围
【发布时间】:2017-10-01 12:12:57
【问题描述】:

我想为我的 mapreduce 代码定义一个辅助函数,它可以用另一个函数(即依赖注入)进行参数化,类似于下面的定义:

var helper = function(f) {
  return function(x) {
    return f(x); // just an example
  };
}

在调用Mongo的mapreduce时,我在作用域中传递了(已经解析的)函数:

var options = {
  scope: {
    doStuff: helper(someFun)
  },
  …
};

var map = function() { … };
var reduce = function(key, values) { doStuff(…); … };

db.collection('test').mapReduce(map, reduce, options);

我希望f 将在返回的函数中包含someFun,并且可以在map 或reduce 函数中使用。但它没有,mapreduce 失败并且 Mongo 报告:

{ MongoError: ReferenceError: f is not defined : …

这可以吗?我是否需要重写我的函数以保留范围/闭包?如果可能的话,我也想避免在范围内定义f,因为我觉得这可能会在未来中断(开发人员忘记将所有必需的功能添加到范围等)

【问题讨论】:

  • 这不是 JavaScript 中的 this 关键字的用途吗?
  • 我很高兴以正确的方式使用this 来解决我的问题,尽管我认为这与我的问题无关。

标签: javascript mongodb scope mapreduce


【解决方案1】:

这就是我的做法:

// re-useable helpers to generate mongodb map functions
// (mongoshell-compatible dependency injection)

// creates a renderDate() function to be used from map() functions
function renderDate() {
  var DAY_MS = 1000 * 60 * 60 * 24;
  var renderDate = t =>
    new Date(DAY_MS * Math.floor(t / DAY_MS)).toISOString().split('T')[0];
}

// generates a map function after injecting code from the mapHelpers() function
function makeMapWith(mapHelpers, mapTemplate) {
  const getFuncBody = fct => {
    var entire = fct.toString();
    return entire.substring(entire.indexOf("{") + 1, entire.lastIndexOf("}"));
  };
  return new Function([
    getFuncBody(mapHelpers),
    getFuncBody(mapTemplate),
  ].join('\n'));
}

const map = makeMapWith(renderDate, function mapTemplate(){
  // the body of this map() function can use renderDate
  // because it's injected by makeMapWith() 
  emit(renderDate(this._id.getTimestamp()), {});
});

// the map function can safely be passed to mongodb's mapReduce()

【讨论】:

    猜你喜欢
    • 2014-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-01
    • 2016-05-07
    相关资源
    最近更新 更多