从NodeJS中的多个MongoDB查询存储数据

时间:2013-05-12 01:07:19

标签: javascript node.js mongodb

好吧,我觉得如果我只是复制整个node.js路线会更容易,这样你就能看到我在说什么。

我正在尝试对MongoDB数据库进行多次查询(每天一次)。查询运行正常,但是当它们触发回调时,我的incrementor变量已经递增。

所以对此:

exports.graph = function(req, res) {

  function pad(num, size) {
    var s = num+"";
    while (s.length < size) s = "0" + s;
    return s;
  }

  database.collection('customerData', function(err, collection) {

    for (var i = 2; i < 18; i++) {

      sDay = pad(i, 2);
      eDay = pad(i + 1, 2);

      collection.find({ 
        DATE: { 
          $gte: sDay + 'APR13:00:00:00',
          $lt: eDay + 'APR13:00:00:00' 
        }
      }, function(err, cursor){
        cursor.toArray(function(err, data){
          var counter = 0;
          for (var point in data) {
            trans = parseInt(data[point].Total_Transaction * 100);
            counter += trans;
          }

          console.log(i, counter / 100);  
        });
      });
    }
  });
}   

我得到了这个输出:

18 22023.29
18 24483.03
18 22644.11
18 23194.31
18 21560.99
18 23024.32
18 24384.93
18 23138.34
18 24400.63
18 28418.6
18 31691.65
18 31111.62
18 42358.74
18 38355.76
18 36787.52
18 42870.19
18 22023.29
18 22644.11
18 24483.03
18 23194.31
18 21560.99
18 23024.32
18 24400.63
18 23138.34
18 24384.93
18 28418.6
18 31691.65
18 31111.62
18 42358.74
18 38355.76
18 36787.52
18 42870.19

这(显然)并不理想 - 数字不一定按照查询被触发的顺序返回,所以找出哪些数据去哪里很重要。

我无法找到一种方法以有意义的方式将我的算术结果存储在查询回调中,以便稍后使用它。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

在旁注中,与您的示例和我的示例不同,您确实应该保存集合引用,而不是每次需要使用它时重新实例化。

至于你的问题,只需将每个调用的逻辑包装在自己的函数中。这样您就可以创建一个闭包,记住每个特定查询的日期。下面我创建了一个示例,其中所有结果都放入一个对象,然后当所有查询完成后,它按顺序输出所有结果。

var _outstanding = 0,
    _results = {};

database.collection('customerData', function(err, collection) {
  for (var i = 2; i < 18; i++) {
    _outstanding++;
    getDay(collection, i, getDayCallback);
  }
});

function getDay (collection, day, callback) {
  sDay = pad(day, 2);
  eDay = pad(day + 1, 2);

  collection.find({ ...query obj... }).toArray(err, data) {
    var counter = 0;
    if (!err) {
      for (var point in data)
        counter += parseInt(data[point].Total_Transaction * 100);
    }

    callback(err, day, counter);
  });
}

function getDayCallback (err, day, count) {
  // ...actually handle any errors, of course...
  _results[day] = count;

  if (--_outstanding === 0) { //display the results in-order when done
    for (var i = 2; i < 18; i++)
      console.log(i, _results[i] / 100)
  }
}

在这个人为的例子中,getDaygetDayCallback可以很容易地组合成一个函数,但在现实世界中,你很可能希望它们保持独立。此外,不确定218的来源,但我猜他们实际上不应该像我一样多次进行硬编码:)。

答案 1 :(得分:1)

@Bret的回答是100%正确的。

我想做一些贡献,以展示如何通过最少的修改来转换代码以包含闭包。因为闭包在这种情况下(经常发生)非常有用,如果可能有助于查看模式。

exports.graph = function(req, res) {

    function pad(num, size) {
        var s = num+"";
        while (s.length < size) s = "0" + s;
        return s;
    }

    database.collection('customerData', function(err, collection) {

        for (var i = 2; i < 18; i++) {

            sDay = pad(i, 2);
            eDay = pad(i + 1, 2);

            collection.find({ 
                DATE: { 
                    $gte: sDay + 'APR13:00:00:00',
                    $lt: eDay + 'APR13:00:00:00' 
                }
            }, (function(i){ //anonymous function which is sync-executed, bringing
                             // 'i' to closure-scope.
                return function(err, cursor){
                    cursor.toArray(function(err, data){
                        var counter = 0;
                        for (var point in data) {
                            trans = parseInt(data[point].Total_Transaction * 100);
                            counter += trans;
                        }

                        console.log(i, counter / 100);  
                    });
                });
            }(i))
        }
    });
}