標籤:
上一篇介紹了如何用express搭建起服務端MVC的開發架構,本篇我們來詳細介紹一下這個Model層,也就是資料庫訪問層。包含如何使用mongodb搭建資料庫,以及如何使用mongoose來訪問資料。 mongodb的安裝和啟動首先我們得安裝mongodb,先去官網( http://www.mongodb.org/downloads)下載安裝包,我的開發環境是Windows,所以下載Windows下的iso檔案,根據提示一路安裝完畢即可,沒什麼需要特別選擇的。安裝完後,為了能在cmd中全域都能啟動mongodb,我們需要配置環境變數,將安裝目錄下的bin目錄配置在系統變數中,接下來,建立一個目錄,用於存放資料庫檔案。我建立的目錄為D:\mongodb\data\db,然後運行cmd,執行命令mongod --dbpath D:\mongodb\data\db,這個時候mongodb就運行起來了,我們就可以用程式來串連資料庫了。 串連資料庫mongodb的預設連接埠是27017,我們在項目中有一個models檔案夾,裡面放置與資料庫連接的資料模型,其中有一個mongodb.js,內容很簡單:
var mongoose = require(‘mongoose‘);mongoose.connect(‘mongodb://localhost/QuestionMaker‘);exports.mongoose = mongoose;
是標準的commonjs模組寫法,先引用mongoose模組,然後串連資料庫,對外暴露mongoose模組。可以看到我們在代碼中去訪問本地的QuestionMaker資料庫。那麼首先我們得有這個資料庫才行。運行cmd,建立一個資料庫use QuestionMakerdb.createCollection("counters")此命令會建立一個名為QuestionMaker的資料庫,並在該庫建立一個集合counters(這個集合我們後續會用到),必須得這麼寫,否則資料庫無法建立。驅動模組寫好了,我們在其他模組中引用該模組後,就可以串連到資料庫了。 使用mongoose操作資料庫我們看到上面用了一個叫做mongoose的模組,它是一個nodejs模組,mongoose提供了Schema、Model、Documents對象,用它可以更加直觀的操作資料庫,所以很多人喜歡這個模組,我們項目中也用它來操作資料庫。為了能以我們熟悉的物件導向的方式來訪問資料庫,我們先根據試題的資料結構來建立一個Schema:
var QuestionSchema = new Schema({ id: String, qtype: Number, name: String, content: String, options: [ { name: String } ], answer: String});Schema可以理解為一個模板,根據此模版,我們可以用mongoose.model來建立出一個Question類,代碼如下:
var Question = mongodb.mongoose.model("Question", QuestionSchema);利用Question類樣本化出的對象帶有很多方法用來訪問/操作資料庫,如save方法,可以儲存一條文檔,也就是document(mongodb中的概念,類似我們以前概念中的一條記錄)。為了儘可能少的對外暴露資料(封裝性),我建立了一個QuestionDAO對象,也就是仿造java中的概念,加一個DAO層,用來提供資料訪問。對外暴露的方法都定義在這個對象上,例如儲存記錄和更新記錄的代碼如下:
//儲存試題QuestionDAO.prototype.save = function(obj, callback){ var instance = new Question(obj); instance.save(function(err){ callback(err, null); });}//更新試題QuestionDAO.prototype.update = function(obj, callback){ Question.findByIdAndUpdate(obj._id, obj, {}, function(err){ callback(err, null); });}用了mongoose提供的save方法和findByIdAndUpdate方法,每一個操作之後都可以傳回呼函數,這樣我們就能把資料庫訪問的結果返回給controller層了。另外,根據業務需求,我們就可以寫更多的方法了,如項目中的list、get、remove,分別用來擷取試題列表、擷取試題、刪除試題。其中list方法中還實現了分頁返回資料。 mongodb實現id自增id自增是資料庫的一個常見需求,在mysql中,只要指定欄位auto_increment即可,在mongodb中,沒有這樣的方法,所以必須得在代碼中實現才行。我們按照官方給出的解決方案,實現questions集合的id自增。id自增功能需要一個輔助的集合來完成,就是我們之前建立好的counters,用來記錄當前的id值為多少。在mongodb命令列中執行db.counters.save({_id: "questionid", seq: 0})完成初始化。_id是mongodb預設提供的一個欄位,我們這裡賦值為questionid,是為了做一個標記,以便在後面能夠尋找出這條記錄。然後在question.js中建立CounterSchema並產生一個Counter類,用來操作counters集合,代碼如下:
var CounterSchema = Schema({ _id: {type: String, required: true}, seq: { type: Number, default: 1 }});var Counter = mongodb.mongoose.model("Counter", CounterSchema);然後,在QuestionSchema的save方法之前,我們應該先去counters中擷取最新id,可以用pre方法來實現,代碼如下:
QuestionSchema.pre(‘save‘, function(next) { var doc = this; Counter.findByIdAndUpdate({_id: ‘questionid‘}, {$inc: { seq: 1} }, function(error, counter) { if(error) return next(error); doc.id = counter.seq; next(); });});QuestionSchema.set(‘toObject‘, { getters: true });如此一來,每次Question執行save方法的時候,都會調用這個函數,從而擷取到遞增後的最新id。 備份和匯入資料庫的備份和匯入當然是必不可少了,比如大家可以拿這我的備份檔案直接匯入來練習,這樣就省去了一步一步建立的步驟。備份資料庫可以使用mongodump命令,用法如下:mongodump -h dbhost -d dbname -o dbdirectory匯入已有的資料庫可以使用mongostore命令,用法如下:mongorestore -h dbhost -d dbname –directoryperdb dbdirectory具體的參數可以在網上搜尋,文章很多,此處不再詳細說明。 用戶端工具mongodb有沒有像mysql那樣的用戶端工具呢?當然有啦,我使用的是robomongo這個工具,簡單好用,介面如下,大家可以嘗試使用。 使用MEAN技術棧開發web應用系列三部曲就到這裡了,再次附上練手項目的地址:https://github.com/Double-Lv/QuestionMaker另外,本系列文章只是一個入門層級的介紹,所寫的代碼以及資料庫的設計基本上都屬於”玩具代碼“,寫一個自己玩的項目還行。在實際的項目中,我們還得考慮各種因素,效能、負載等等,更多話題有待研究。
用“MEAN”技術棧開發web應用(三)用mongodb搭建資料庫