【问题标题】:Extract common code from sails.js / mongodb从sails.js/mongodb中提取公共代码
【发布时间】:2014-09-15 09:50:00
【问题描述】:

我目前正在尝试将sails.js 与mongodb 一起使用,我需要一些自定义mapReduce 函数来对数据进行分组。

现在我可以通过使用 waterline 的 native 函数来实现我想要的,但是有一些问题。

这些函数实际上只有很小的变化,但我发现自己不断重复以下代码:

function getSomeData() {
  // First-query
  Log.native(function(err, logCollection) {

    var mapFunction = function() {
      function dateFormatter(date) {
        return date.getFullYear() + "-" + (date.getMonth() + 1)
      }

      //! Generate Grouping Key
      emit(dateFormatter(this.emb_date), this.bad_qty)
    }

    var reduceFunction = function (key, values) {
      return Array.sum(values);
    }

    var outputControl = {
      out: {inline: 1},
      //! Filters
      query: {order_type: product}
    }

    logCollection.mapReduce(mapFunction, reduceFunction, outputControl, function (err, result) {
      if (err) { 
        callback(err); 
        return; 
      }

      var resultSet = [];

      //! post-processing
      for (var i = 0; i < result.length; i++) {
        //.....
      }

      callback(err, resultSet);
    });
  });
}

第二次查询:

function getAnotherData() {
  Log.native(function(err, logCollection) {

    var mapFunction = function() {
      //! Generate Grouping Key
      emit(dateFormatter(this.product), this.bad_qty)
    }

    var reduceFunction = function (key, values) {
      return Array.sum(values);
    }

    var outputControl = {
      out: {inline: 1},
      //! Filters
      query: {order_type: product}
    }

    logCollection.mapReduce(mapFunction, reduceFunction, outputControl, function (err, result) {
      if (err) { 
        callback(err); 
        return; 
      }

      var resultSet = [];

      //! post-processing
      for (var i = 0; i < result.length; i++) {
        //......
      }

      callback(err, resultSet);
    });
  });
}

如你所见,这两个sn-p有很多共同的代码,只有三个地方不同(生成分组键、过滤器、后处理)。

所以我真的很想提取公共部分以使我的代码更干净,但没有成功。

我首先尝试让 dateFromatter 由回调提供,而不是像下面这样的硬编码:

function dateFormatter(data) {
  return data.emb_date.getFullYear() + "-" + (data.emb_date.getMonth() + 1)
}


function getSomeData(groupingKey) {
  // First-query
  Log.native(function(err, logCollection) {

    var mapFunction = function() {
      //! Generate Grouping Key
      emit(groupingKey(this.emb_date), this.bad_qty)
    }

    var reduceFunction = function (key, values) {
      return Array.sum(values);
    }

    var outputControl = {
      out: {inline: 1},
      //! Filters
      query: {order_type: product}
    }

    logCollection.mapReduce(mapFunction, reduceFunction, outputControl, function (err, result) {
      if (err) { 
        callback(err); 
        return; 
      }

      var resultSet = [];

      //! post-processing
      for (var i = 0; i < result.length; i++) {
        //.....
      }

      callback(err, resultSet);
    });
  });
}

但没有任何运气,我不断收到如下错误:

 MongoError: exception: ReferenceError: groupingKey is not defined near 'emit(groupingKey(this), this.bad_qty'  (line 3)
    at Object.toError (/home/brianhsu/zh800/dashboard/node_modules/sails-mongo/node_modules/mongodb/lib/mongodb/utils.js:114:11)

如果我想减少那些重复的代码部分应该怎么做?

【问题讨论】:

    标签: javascript mongodb sails.js waterline


    【解决方案1】:

    最后我发现我需要将名为 'scope' 的选项传递给 mongodb,我想出了以下解决方案,效果很好。

    exports.defineOn = function(options) {
    
      var model = options.model
      var groupingFunction = options.groupingFunction
      var mongoFilters = options.mongoFilters
      var customFilter = options.customFilter
      var converter = options.converter
      var sorting = options.sorting
    
      return function(callback) {
        model.native(function(err, collection) {
          var mapFunction = function() { emit(groupingFunction(this), this.bad_qty) }
          var reduceFunction = function(key, values) { return Array.sum(values); }
          var mapReduceOptions = {
            out: {inline: 1},
            query: mongoFilters,
            scope: {
              groupingFunction: groupingFunction, 
              mongoFilters: mongoFilters, 
              customFilter: customFilter,
              converter: converter
            }
          }
    
          var processCallback = function (err, result) {
            if (err) {
              callback(err);
              return;
            }
    
            if (sorting) {
              result.sort(sorting);
            }
    
            var resultSet = [];
    
            for (var i = 0; i < result.length; i++) {
              if (customFilter && customFilter(result[i])) {
                resultSet.push(converter(result[i]));
              } else if (!customFilter) {
                resultSet.push(converter(result[i]));
              }
            }
    
            callback(err, resultSet);
          }
    
          collection.mapReduce(mapFunction, reduceFunction, mapReduceOptions, processCallback);
        });
      }
    }
    

    用法:

    function machineDetail (year, month, date, machine, callback) {
    
        var startDate = new Date(+year, +(month-1), +date);
        var endDate = new Date(+year, +(month-1), (+date) + 1);
    
        var mapReducer = MapReducer.defineOn({
          model: Log,
          groupingFunction: function(data) {
            return {date: data.emb_date, error: data.defact_id};
          },
          mongoFilters: {
            mach_id: machine,
            emb_date: {$gte: startDate, $lt: endDate}
          },
          converter: function (data) {
            return {
              name: data._id,
              value: data.value,
            };
          }
        });
    
        mapReducer(callback);
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-19
      • 2018-04-08
      相关资源
      最近更新 更多