1. 程式人生 > >node.js對mongodb的連接&增刪改查(附async同步流程控制)

node.js對mongodb的連接&增刪改查(附async同步流程控制)

color var literal int lba node () n! node.js

1.啟動mongodb數據庫

官網下載mongodb數據庫

在mongodb根目錄下創建文件夾:假設取名為test。
我們認為test就是mongodb新建的數據庫一枚。

創建批處理文件 xxx.bat,內容如下:

運行e盤mongodb文件夾下bin目錄下的 mongod.exe,參數為
-dbpath E:\mongodb\test。

E:\mongodb\bin\mongod.exe -dbpath E:\mongodb\test

這樣就啟動了mongodb下test數據庫的服務器。

2.加載mongodb模塊

在我們的node.js項目中直接npm入mongodb模塊

npm install mongodb --save


3.依賴mongodb模塊

在想要寫對mongodb的增刪改查邏輯的js文件下加入以下依賴

var mongo = require("mongodb");

4.通用小函數

寫了幾個通用的小函數,最後創建一個對象,將函數全都掛到對象上,最後把對象exports出去即可。

/**
 * 創建數據庫服務器並開發名為databaseName的數據庫
 * @param host ip
 * @param port 端口
 * @param databaseName
 * @return  打開失敗返回-1 ,成功返回database
 */
function openDatabase(host,port,databaseName){
    //創建數據庫所在的服務器
    var server = new mongo.Server(host, port, {auto_reconnect: true});
    var db = new mongo.Db(databaseName, server, {safe: true});
    db.open(function (err, db) {
        if (err) {
            console.log(‘打開數據庫失敗‘);
            return -1;
        }
        else {
            console.log(‘打開數據庫成功‘);

        }

    });
    return db;
}
/**
 * 連接數據集合
 * @param db 數據庫
 * @param collectionName 數據集合名稱
 * @return 成功返回collection,失敗返回-1
 */
function openCollection(db,collectionName){
    db.collection(collectionName,{safe:true},function(errcollection,collection){
        if(!errcollection){
            console.log(‘連接數據集合成功‘);
            return collection;

        }else{
            console.log(‘連接數集合失敗‘);
            return -1;
        }
    });


}
/**
 * 插入數據
 * @param collection
 * @param tmp 要插入的數據
 * @return 成功返回collection,失敗返回-1
 */
function insertCollection(collection,tmp){
    //var tmp = {username:‘hello‘,password:1};
    collection.insert(tmp,{safe:true},function(err, result){
        if(err){
            console.log(‘傳入數據集合失敗‘+tmp);
            return -1;
        }else {
            console.log(‘插入數據集合成功‘+result);

        }
    });
    return collection;
}
/**
 * 查詢數據集合 沒有條件
 * @param collection
 * @return 成功返回查詢到的數據集合內容,失敗返回-1
 */
function findCollectionNoCondition(collection){
    collection.find().toArray(function(errfind,cols){
        if(!errfind){
            console.log(‘查詢數據集合成功‘+JSON.stringify(cols));
            return JSON.stringify(cols);
        }else {
            console.log(‘查詢數據集合失敗‘);
            return -1;
        }
    });
}
/**
 * 查詢數據集合 有條件
 * @param collection
 * @return 成功返回查詢到的數據集合內容,失敗返回-1
 */
function findCollectionHasCondition(collection,tmp){
    collection.find(tmp).toArray(function(errfind,cols){
        if(!errfind){
            console.log(‘查詢數據集合成功‘+JSON.stringify(cols));
            return JSON.stringify(cols);
        }else {
            console.log(‘查詢數據集合失敗‘);
            return -1;
        }
    });
}
/**
 * 刪除數據集合
 * @param collection
 * @param tmp
 * @return 成功返回數據集合,失敗返回-1
 */
function removeCollection(collection,tmp){
    //var tmp = {username:‘hello‘,password:1};
    collection.remove(tmp,{safe:true},function(err, count){
        if(err){
            console.log(‘刪除數據集合失敗‘+tmp);
            return -1;
        }else {
            console.log(‘刪除數據集合成功‘+count);
            return collection;
        }
    });
}



5.async模塊解決node.js異步架構下同步邏輯的實現

看到《超實用的node.js代碼段》這本書上,講到Node.js是異步I/O驅動,所以在我們順序運行上面的幾個函數的時候,一定會遇到一個問題:如果前面de函數耗時長,那麽後面的函數不會等前面的函數運行完,而是直接運行。但是我的前一個函數的運行結果是要被後一個函數使用的呀。

這時候就需要在異步I/O下進行串行控制流控制。

書中介紹了async模塊,手續愛你第三方引入。

npm install async --save
  • 1

require進來

var async=require("async");
  • 1

使用方法:
Nodejs異步流程控制Async

我這裏使用的是waterfall瀑布模式流程控制
github waterfall機制使用demo

然後我就天真的使用了

 //使用async瀑布模型流程控制執行 數據庫的連接查詢
    async.waterfall([
        function(callback){
            var db;
            db=user.openDatabase("localhost",27017,"test");
            callback(null,db);
        },
        function(db,callback){
            var collection;
            if(db!=-1){
                collection=user.openCollection(db,‘users‘);
            }
            callback(null,collection);
        },
        function(collection,callback){
            var res;
            if(collection!=-1){
                res=user.findCollectionNoCondition(collection);
                console.log(res);
                callback(null,3);
            }
        }
    ],function(err,result){
        console.log("async瀑布模型流程控制執行成功"+result);
    })
結果還是第二個函數先於第一個函數運行成功,導致第三個函數不能正確運行。

**********************************************************************
一、使用模塊Q的promise機制實現數據庫操作的同步問題

1.install

npm install q --save

2.require

var Q=require(‘q‘);

3.重寫數據庫CRUD操作方法

/**
 * 創建數據庫服務器並開發名為databaseName的數據庫
 * @param host ip
 * @param port 端口
 * @param databaseName
 * @return  打開失敗返回-1 ,成功返回database
 */
function openDatabase(host,port,databaseName,collectionName){
    //創建數據庫所在的服務器

    var deferred = Q.defer();
    var server = new mongo.Server(host, port, {auto_reconnect: true});
    var db = new mongo.Db(databaseName, server, {safe: true});
    db.open(function (err, db) {
        if (err) {
            console.log(‘打開數據庫失敗‘);
            deferred.reject(err);
        }
        else {
            console.log(‘打開數據庫成功‘);
            deferred.resolve([db,collectionName]);

        }

    });
    return deferred.promise;
}
/**
 * 連接數據集合
 * @param db 數據庫
 * @param collectionName 數據集合名稱
 * @return 成功返回collection,失敗返回-1
 */
function openCollection(db,collectionName){
    var deferred = Q.defer();
    db.collection(collectionName,{safe:true},function(errcollection,collection){
        if(!errcollection){
            console.log(‘連接數據集合成功‘);
            deferred.resolve(collection);

        }else{

            console.log(‘連接數集合失敗‘);
            deferred.reject(errcollection);
        }
    });
    return deferred.promise;

}
/**
 * 插入數據
 * @param collection
 * @param tmp 要插入的數據
 * @return 成功返回collection,失敗返回-1
 */
function insertCollection(collection,tmp){
    //var tmp = {username:‘hello‘,password:1};
    collection.insert(tmp,{safe:true},function(err, result){
        if(err){
            console.log(‘傳入數據集合失敗‘+tmp);
            return -1;
        }else {
            console.log(‘插入數據集合成功‘+result);

        }
    });
    return collection;
}
/**
 * 查詢數據集合 沒有條件
 * @param collection
 * @return 成功返回查詢到的數據集合內容,失敗返回-1
 */
function findCollectionNoCondition(collection){
    var deferred = Q.defer();
    collection.find().toArray(function(errfind,cols){
        if(!errfind){
            console.log(‘查詢數據集合成功‘+JSON.stringify(cols));
            deferred.resolve(JSON.stringify(cols));
        }else {
            console.log(‘查詢數據集合失敗‘);
            deferred.reject(errfind);
        }
    });

    return deferred.promise;
}
/**
 * 查詢數據集合 有條件
 * @param collection
 * @return 成功返回查詢到的數據集合內容,失敗返回-1
 */
function findCollectionHasCondition(collection,tmp){
    collection.find(tmp).toArray(function(errfind,cols){
        if(!errfind){
            console.log(‘查詢數據集合成功‘+JSON.stringify(cols));
            return JSON.stringify(cols);
        }else {
            console.log(‘查詢數據集合失敗‘);
            return -1;
        }
    });
}
/**
 * 刪除數據集合
 * @param collection
 * @param tmp
 * @return 成功返回數據集合,失敗返回-1
 */
function removeCollection(collection,tmp){
    //var tmp = {username:‘hello‘,password:1};
    collection.remove(tmp,{safe:true},function(err, count){
        if(err){
            console.log(‘刪除數據集合失敗‘+tmp);
            return -1;
        }else {
            console.log(‘刪除數據集合成功‘+count);
            return collection;
        }
    });
}

裏面的關鍵點是:

  • 定義defered對象var deferred = Q.defer();
  • 定義函數成功執行的resolve對象deferred.resolve(JSON.stringify(cols));
  • 定義函數成功失敗的error對象 deferred.reject(errfind);
  • 最後返回一個新的promise對象,用來return deferred.promise;

4.鏈式調用

  user.openDatabase("localhost",27017,"test","users")
        .then(function(data){
            return user.openCollection(data[0],data[1])
        })
        .then(user.findCollectionNoCondition)
        .done(function(data){
            console.log(‘promise執行成功‘);
        },function(err){
           console.log("promise執行失敗:"+err);
        });

5.log打印結果

GET / 304 55.922 ms - -
打開數據庫成功
連接數據集合成功
GET /stylesheets/style.css 304 6.048 ms - -
查詢數據集合成功[{"_id":"57731d3a239f75379769ce31","username":"liuchen","password":"12345"},{"_id":"577328ab5c8d6cf43b3e214d","username":"hello","password":1},{"_id":"577331f35c8d6cf43b3e214e","username":"hello","password":1},{"_id":"57733bf400a7090c35122844","username":"hello","password":1},{"_id":"57733c0300a7090c35122845","username":"hello","password":1},{"_id":"57733c0af8d7813443d51c27","username":"hello","password":1}]
promise執行成功
















node.js對mongodb的連接&增刪改查(附async同步流程控制)