Node.js | MongoDB count():在插入数据之前和之后获取计数

时间:2017-01-21 16:37:02

标签: javascript node.js mongodb

我正在尝试获取数据库中的项目数,以确认数据插入是否成功。

  1. 插入前计算
  2. 插入
  3. 插入后计算
  4. Console.log摘要
  5. 注意:我知道这可以使用一些简单的函数来实现:

    dbName.equal(insertSize, result.insertedCount)
    

    但是,我是javascript的新手,我认为我已经遇到了实现异步回调的需求,所以我想弄清楚这一点。

    插入功能

    var insertMany = function() {
    
        // get initial count
        var count1 = getDbCount();
    
        // Insert new 'data'
        MongoClient.connect(url, function(err, db) {
            var col = db.collection(collectionName);
            col.insert(data, {w:1}, function(err,result) {});
            db.close();
        });
    
        /** This needs to be implemented through next/callback
            after the insert operation  **/
        var count2 = getDbCount(); 
    
        /** These final console logs should be executed after all
            other operations are completed **/    
        console.log('[Count] Start: ' + count1 + ' | End:' +count2);
        console.log('[Insert] Expected: ' + data.length + ' | Actual: ' + (count2 - count1));
    
    };
    

    获取数据库计数功能

    var getDbCount = function() {
        MongoClient.connect(url, function(err, db) {
            if (err) console.log(err);
    
            var col = db.collection(collectionName);
    
            col.count({}, function(err, count) {
                if (err) console.log(err);
                db.close();
                console.log('docs count: ' + count);
                // This log works fine
            });
    
        });
    
        return count; // this is returning as undefined since this is
                      // executing before the count operation is completed
    };
    

    我收到错误,因为在所需的操作完成之前发生了返回。

    感谢您的帮助。

    [编辑]带有承诺的getCount函数

    我已将承诺添加到getCount函数作为开头:

    var getCount = function() {
    
        var dbCount = 0;
    
        var promise = new Promise(function(resolve, reject) {
    
            MongoClient.connect(url, function(err, db) {
    
                if (err) {
                    console.log('Unable to connect to server', err);
                } else {
                    console.log('Database connection established:' + dbName);
                }
    
                // Get the collection
                var col = db.collection(collectionName);
    
                col.count({}, function(err, count) {
                    if (err) console.log(err);
                    db.close();
                    console.log('docs count: ' + count);
                    resolve(null);
                    dbCount = count;
                });
    
            });
    
        });
    
        promise.then(function() {
            return dbCount;
        });
    
    };
    
    console.log(getCount());
    

    输出仍然是:     未定义     建立数据库连接:testdb     docs:500

    然后({return count})代码仍然在promise {db.count()}之前执行。它在数据库操作完成之前返回undefined。

2 个答案:

答案 0 :(得分:2)

通常,您遇到的问题是,当函数返回时,您希望值已存在。对于异步功能,通常情况并非如此。有关异步处理的大量信息(不要像在Java中那样与并行处理混淆)。

我创建了一个适合您情况的示例:

https://jsfiddle.net/rh3gx76x/1/

var dummyCount = 5
getCount = function() {
    return new Promise(function(resolve, reject) {
      setTimeout(function() { // this would be your db call, counting your documents
          resolve(dummyCount); // dummy for number of documents found
      }, 100 * Math.random());
  });
};

insertMany = function() {
    return new Promise(function(resolve, reject) {
      setTimeout(function() { // this would be your db call, writing your documents
          dummyCount += 2;
          resolve();
      }, 100 * Math.random());
  });
};

runIt = function(callback) {
   var count1;
   getCount().then(function(count) {
        console.log("First callback with value ", count);
      count1 = count;
        insertMany().then(function() {
         getCount().then(function(count2){
            console.log("Second callback with value ", count2);
                callback(null, count1, count2);
         });
      })
   })
}

runIt(function(err, count1, count2) {
   console.log("count1: " + count1 + ", count2: " + count2);
});

最后一件事。您可能想要查看“异步”包。这对于提供大量辅助函数和控制流程的问题有很大帮助。

答案 1 :(得分:0)

在操作完成之前返回的原因是nodejs的asynchronous设计,继承自javascript。当程序向前移动并遇到Mongoose.connect()时,return的回调将被执行操作。

您还没有提供使您在错误声明中找到的解决方法,因此我无法评论您在那里做了什么错误。但是,考虑到您第一次完成开始的工作,确保Mongoose.connect()完成然后执行return语句的最佳方法是使用JavaScript的promise。使用promises将使Mongoose.connect()执行,然后将控件传递给return语句。

您的代码将类似于:

插入功能

var insertMany = function() {

// get initial count
var count1 = getDbCount();

// Insert new 'data'
var promise = new Promise(
    function(resolve,reject){
      MongoClient.connect(url, function(err, db) {
        var col = db.collection(collectionName);
        col.insert(data, {w:1}, function(err,result) {});
        db.close();
        resolve(null);
      });
    }
  );
  promise.then(function(val){    
    var count2 = getDbCount();

    /** These final console logs should be executed after all
    other operations are completed **/
    console.log('[Count] Start: ' + count1 + ' | End:' +count2);
    console.log('[Insert] Expected: ' + data.length + ' | Actual: ' + (count2 - count1));
});

同样,您可以向GetDB函数添加承诺。 执行承诺时的关键点是:

  1. then()包含执行promise后要同步执行的函数部分。它由resolve调用,传递的参数在catch函数的回调中接收。
  2. catch()包含在promise中遇到错误时调用的函数部分。它由reject调用,传递的参数在catch函数的回调中接收。
  3. 编辑:承诺的另一种选择是async.js,只是它与外部模块不同,与承诺不同。