NodeJS簡易部落格系統(四)Mongoose入門學習
一、模式(schemas)
1、定義schema
Mongoose的一切都始於一個Schema。每個schema對映到MongoDB的集合
(collection)和定義該集合(collection)中的文件的形式。
var mongoose = require('mongoose'); var Schema = mongoose.Schema; var blogSchema = new Schema({ title: String, author: String, body: String, comments: [{ body: String, date: Date }], date: { type: Date, default: Date.now }, hidden: Boolean, meta: { votes: Number, favs: Number } }); |
如果想後續新增額外的鍵(keys) ,使用Schema#add方法。在blogSchema每個key在我們的檔案將被轉換為相關SchemaType定義一個屬性。允許使用的SchemaTypes:
- String
- Number
- Date
- Buffer
- Boolean
- Mixed
- ObjectId
- Array
用default來設定預設值。
2、模型建立
使用剛剛的schema定義,我們需要將我們的blogschema轉成我們可以用的模型。
為此,我們通過 mongoose.model(modelName, schema) :
var Blog = mongoose.model('Blog', blogSchema); |
3、自定義文件例項方法
// define a schema var animalSchema = new Schema({ name: String, type: String }); // assign a function to the "methods" object of our animalSchema animalSchema.methods.findSimilarTypes = function(cb) { return this.model('Animal').find({ type: this.type }, cb); }; |
呼叫:
var Animal = mongoose.model('Animal', animalSchema); var dog = new Animal({ type: 'dog' }); dog.findSimilarTypes(function(err, dogs) { console.log(dogs); // woof }); |
4、自定義文件靜態例項方法
// assign a function to the "statics" object of our animalSchema animalSchema.statics.findByName = function(name, cb) { return this.find({ name: new RegExp(name, 'i') }, cb); }; var Animal = mongoose.model('Animal', animalSchema); Animal.findByName('fido', function(err, animals) { console.log(animals); }); |
二、模型(models)
Models 是從 Schema
編譯來的建構函式。 它們的例項就代表著可以從資料庫儲存和讀取的 documents。 從資料庫建立和讀取 document 的所有操作都是通過 model 進行的。
1、簡單例項
schema檔案
var mongoose = require("mongoose"); module.exports = new mongoose.Schema({ username: String, password: String, isadmin:{ type:Boolean, default:false } }); |
model檔案
var mongoose = require("mongoose"); var userschama = require("../schemas/users"); module.exports = mongoose.model("User",userschama); |
2、CRUD操作
1、Create
model物件.save() |
2、Retrieve
用 mongoose 查詢文件相當容易啦,它支援 MongoDB 的高階( rich )查詢語法。 查詢文件可以用 model 的 find, findById, findOne, 和 where 這些靜態方法。查詢物件的size為small並且建立時間為近一年的資料:
model物件.find({ size: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);。 |
3、Update
model 的 update 方法可以修改資料庫中的文件,不過不會把文件返回給應用層。如果想更新單獨一條文件並且返回給應用層,可以使用 findOneAndUpdate 方法。
4、Delete
model
的 remove
方法可以刪除所有匹配查詢條件( conditions
)的文件。
Tank.remove({ size: 'large' }, function (err) { if (err) return handleError(err); // todo after removing }); |
三、文件(documents)
1、更新
Document 更新的方法同樣有很多,我們先看看一個傳統的實現,使用 findById:
Object.findById(id, function (err, object) { object.size = 'large'; |
這個方法先檢索資料,接著更新(使用了 save)。 如果僅僅需要更新而不需要獲取該資料, Model#update 就很適合:
Object.update({ _id: id }, { $set: { size: 'large' }}, callback); |
如果我們確實需要返回文件,這個方法更適合:
Object.findByIdAndUpdate(id, { $set: { size: 'large' }}, { new: true }, function (err, object) { if (err) return handleError(err); res.send(object); }); |
findAndUpdate/Remove 系列靜態方法查詢並返回最多1個文件。
注意:findAndUpdate/Remove 不會修改資料庫時執行任何鉤子或驗證。 可以使用 runValidators 選項 獲取一個驗證的限制子集(待修改)。 但是你需要鉤子和全文件驗證,還是先 query 後 save 吧。
2、覆蓋
可以用 .set() 覆蓋整個文件。如果你要修改 在中介軟體中被儲存的文件,這樣就很方便。
Object.findById(id, function (err, object) { if (err) return handleError(err); // Now `otherObject` is a copy of `object` otherObject.set(object); }); |
3、子文件(Subdocument)
子文件是指巢狀在另一個文件中的文件。 在 Mongoose 中,這意味著你可以在裡巢狀另一個 schema。 Mongoose 子文件有兩種不同的概念:子文件陣列和單個巢狀子文件。
var childSchema = new Schema({ name: 'string' }); var parentSchema = new Schema({ |
子文件與普通 document 類似。巢狀schema可以有自己的中介軟體、自定義檢驗邏輯、 虛擬值以及其他頂層schemas可用的特性。兩者主要的不同點是子文件不能單獨儲存,他們會在他們的頂級文件儲存時儲存。
var Parent = mongoose.model('Parent', parentSchema); // `parent.children[0].save()` 無操作,雖然他觸發了中介軟體 |
子文件跟普通 document一樣有save和validate中介軟體。呼叫父文件的save()會觸發其所有子文件的save()中介軟體,validate()中介軟體同理。
childSchema.pre('save', function (next) { var parent = new Parent({ children: [{ name: 'invalid' }] }); |
子文件的 pre('save') 和 pre('validate') 中介軟體執行於 頂層document的pre('save') 之前,頂層 document的pre('validate')之後。 因為save()前的驗證就是一個內建中介軟體。
// 一下程式碼順序打出 1-4 childSchema.pre('validate', function(next) { childSchema.pre('save', function(next) { var parentSchema = new mongoose.Schema({ parentSchema.pre('validate', function(next) { parentSchema.pre('save', function(next) { |
查詢子文件
每個子文件都有一個預設的_id 。Mongoose document陣列有一個特別的id方法,這個方法只要傳入_id 就能返回文件陣列中特定文件。
var doc = parent.children.id(_id); |
新增子文件到陣列
Mongoose 陣列方法有 push、 unshift、 addToSet、 及其他:
var Parent = mongoose.model('Parent'); // create a comment parent.save(function (err) { |
create 方法可以新建子文件但不加入陣列。
var newdoc = parent.children.create({ name: 'Aaron' }); |
刪除子文件
每個子文件都有 remove方法。另外,對於子文件陣列,有一個等效方法 .pull()。 對於單個巢狀子文件,remove()與把這個文件的值設為null等效。
// 等效於 `parent.children.pull(_id)` parent.children.id(_id).remove(); // 等效於 `parent.child = null` parent.child.remove(); parent.save(function (err) { if (err) return handleError(err); console.log('the subdocs were removed'); }); |
掌握了這些就能應付這個小專案了,如果要看詳細api請參考官方文件。