从sails.js / mongodb中提取常用代码

时间:2014-09-15 09:50:00

标签: javascript mongodb sails.js waterline

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

现在我可以通过使用水线的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);
    });
  });
}

正如您所看到的,这两个代码段共享许多常用代码,只有三个区别(生成分组键,过滤器,后处理)。

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

我首先尝试使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)

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

1 个答案:

答案 0 :(得分:1)

最后我发现我需要通过名为&#39; scope&#39;对于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);
  }
相关问题