Mongoose 筆記

Mongoose 筆記

官網指南

參考鏈接

名詞解釋

Schema: 一種以文件形式存儲的數(shù)據庫模型骨架,不具備數(shù)據庫的操作能力

Model: 由Schema發(fā)布生成的模型,具有抽象屬性和行為的數(shù)據庫操作對

Entity: 由Model創(chuàng)建的實體,他的操作也會影響數(shù)據庫

Schema、Model、Entity的關系請牢記,Schema生成Model,Model創(chuàng)造Entity,Model和Entity都可對數(shù)據庫操作造成影響,但Model比Entity更具操作性。

鏈接數(shù)據庫&創(chuàng)建模型


var mongoose = require('mongoose');    //引用mongoose模塊

var db = mongoose.createConnection('localhost','test'); //創(chuàng)建一個數(shù)據庫連接

db.on('error',console.error.bind(console,'連接錯誤:'));

db.once('open',function(){

//一次打開記錄

});

//定義一個Schema

var PersonSchema = new mongoose.Schema({

name:String  //定義一個屬性name,類型為String

});

//將該Schema發(fā)布為Model

var PersonModel = db.model('Person',PersonSchema);

//如果該Model已經發(fā)布,則可以直接通過名字索引到,如下:

//var PersonModel = db.model('Person');

//如果沒有發(fā)布,上一段代碼將會異常

//用Model創(chuàng)建Entity

var personEntity = new PersonModel({name:'Krouky'});

//打印這個實體的名字看看

console.log(personEntity.name); //Krouky

我們甚至可以為此Schema創(chuàng)建方法


//為Schema模型追加speak方法

PersonSchema.methods.speak = function(){

console.log('我的名字叫'+this.name);

}

var PersonModel = db.model('Person',PersonSchema);

var personEntity = new PersonModel({name:'Krouky'});

personEntity.speak();//我的名字叫Krouky

//Entity是具有具體的數(shù)據庫操作CRUD的

personEntity.save();  //執(zhí)行完成后,數(shù)據庫就有該數(shù)據了

//如果要執(zhí)行查詢,需要依賴Model,當然Entity也是可以做到的

PersonModel.find(function(err,persons){

//查詢到的所有person

});

查詢

通常有2種查詢方式,一種是直接查詢,一種是鏈式查詢(2種查詢都是自己命名的)

直接查詢

在查詢時帶有回調函數(shù)的,稱之為直接查詢,查詢的條件往往通過API來設定,例如:


PersonModel.findOne({'name.last':'dragon'},'some select',function(err,person){

//如果err==null,則person就能取到數(shù)據

});

鏈式查詢

在查詢時候,不帶回調,而查詢條件通過API函數(shù)來制定,例如:


var query = PersonModel.findOne({'name.last':'dragon'});

query.select('some select');

query.exec(function(err,pserson){

//如果err==null,則person就能取到數(shù)據

});

因為query的操作始終返回自身,我們可以采用更形象的鏈式寫法


Person

.find({ occupation: /host/ })

.where('name.last').equals('Ghost')

.where('age').gt(17).lt(66)

.where('likes').in(['vaporizing', 'talking'])

.limit(10)

.sort('-occupation')

.select('name occupation')

.exec(callback);

更新

有許多方式來更新文件,以下是常用的傳統(tǒng)方式:


PersonModel.findById(id,function(err,person){

person.name = 'MDragon';

person.save(function(err){});

});

這里,利用Model模型查詢到了person對象,該對象屬于Entity,可以有save操作,如果使用Model`操作,需注意:


PersonModel.findById(id,function(err,person){

person.name = 'MDragon';

var _id = person._id; //需要取出主鍵_id

delete person._id;    //再將其刪除

PersonModel.update({_id:_id},person,function(err){});

//此時才能用Model操作,否則報錯

});

update第一個參數(shù)是查詢條件,第二個參數(shù)是更新的對象,但不能更新主鍵,這就是為什么要刪除主鍵的原因。

當然這樣的更新很麻煩,可以使用$set屬性來配置,這樣也不用先查詢,如果更新的數(shù)據比較少,可用性還是很好的:


PersonModel.update({_id:_id},{$set:{name:'MDragon'}},function(err){});

需要注意,Document的CRUD操作都是異步執(zhí)行,callback第一個參數(shù)必須是err,而第二個參數(shù)各個方法不一樣,update的callback第二個參數(shù)是更新的數(shù)量,如果要返回更新后的對象,則要使用如下方法


Person.findByIdAndUpdate(_id,{$set:{name:'MDragon'}},function(err,person){

console.log(person.name); //MDragon

});

類似的方法還有findByIdAndRemove,如同名字,只能根據id查詢并作update/remove操作,操作的數(shù)據僅一條

新增

如果是Entity,使用save方法,如果是Model,使用create方法


//使用Entity來增加一條數(shù)據

var krouky = new PersonModel({name:'krouky'});

krouky.save(callback);

//使用Model來增加一條數(shù)據

var MDragon = {name:'MDragon'};

PersonModel.create(MDragon,callback);

兩種新增方法區(qū)別在于,如果使用Model新增時,傳入的對象只能是純凈的JSON對象,不能是由Model創(chuàng)建的實體,原因是:由Model創(chuàng)建的實體krouky雖然打印是只有{name:'krouky'},但是krouky屬于Entity,包含有Schema屬性和Model數(shù)據庫行為模型。如果是使用Model創(chuàng)建的對象,傳入時一定會將隱藏屬性也存入數(shù)據庫,雖然3.x追加了默認嚴格屬性,但也不必要增加操作的報錯

刪除

和新增一樣,刪除也有2種方式,但Entity和Model都使用remove方法

Sub Docs

如同SQL數(shù)據庫中2張表有主外關系,Mongoose將2個Document的嵌套叫做Sub-Docs(子文檔)

簡單的說就是一個Document嵌套另外一個Document或者Documents:


var ChildSchema1 = new Schema({name:String});

var ChildSchema2 = new Schema({name:String});

var ParentSchema = new Schema({

children1:ChildSchema1,  //嵌套Document

children2:[ChildSchema2]  //嵌套Documents

});

Sub-Docs享受和Documents一樣的操作,但是Sub-Docs的操作都由父類去執(zhí)行


var ParentModel = db.model('Parent',parentSchema);

var parent = new ParentModel({

children2:[{name:'c1'},{name:'c2'}]

});

parent.children2[0].name = 'd';

parent.save(callback);

parent在執(zhí)行保存時,由于包含children2,他是一個數(shù)據庫模型對象,因此會先保存chilren2[0]和chilren2[1]。

如果子文檔在更新時出現(xiàn)錯誤,將直接報在父類文檔中,可以這樣處理:


ChildrenSchema.pre('save',function(next){

if('x' === this.name) return next(new Error('#err:not-x'));

next();

});

var parent = new ParentModel({children1:{name:'not-x'}});

parent.save(function(err){

console.log(err.message); //#err:not-x

});

驗證器

required 非空驗證

min/max 范圍驗證(邊值驗證)

enum/match 枚舉驗證/匹配驗證

validate 自定義驗證規(guī)則

以下是綜合案例:


var PersonSchema = new Schema({

name:{

type:'String',

required:true //姓名非空

},

age:{

type:'Nunmer',

min:18,      //年齡最小18

max:120    //年齡最大120

},

city:{

type:'String',

enum:['北京','上海']  //只能是北京、上海

},

other:{

type:'String',

validate:[validator,err]  //validator是一個驗證函數(shù),err是驗證失敗的錯誤信息

}

});

驗證失敗

如果驗證失敗,則會返回err信息,err是一個對象該對象屬性如下

err.errors //錯誤集合(對象)

err.errors.color //錯誤屬性(Schema的color屬性)

err.errors.color.message //錯誤屬性信息

err.errors.path //錯誤屬性路徑

err.errors.type //錯誤類型

err.name //錯誤名稱

err.message //錯誤消息

一旦驗證失敗,Model和Entity都將具有和err一樣的errors屬性

Middleware中間件

什么是中間件

中間件是一種控制函數(shù),類似插件,能控制流程中的init、validate、save、remove`方法

中間件的分類

中間件分為兩類

Serial串行

串行使用pre方法,執(zhí)行下一個方法使用next調用


var schema = new Schema(...);

schema.pre('save',function(next){

//做點什么

next();

});

Parallel并行

并行提供更細粒度的操作


var schema = new Schema(...);

schema.pre('save',function(next,done){

//下一個要執(zhí)行的中間件并行執(zhí)行

next();

doAsync(done);

});

中間件特點

一旦定義了中間件,就會在全部中間件執(zhí)行完后執(zhí)行其他操作,使用中間件可以霧化模型,避免異步操作的層層迭代嵌套

使用范疇

復雜的驗證

刪除有主外關聯(lián)的doc

異步默認

某個特定動作觸發(fā)異步任務,例如觸發(fā)自定義事件和通知

例如,可以用來做自定義錯誤處理


schema.pre('save',function(next){

var err = new Eerror('some err');

next(err);

});

entity.save(function(err){

console.log(err.message); //some err

});

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Mongodb 配置選項 通常在mongod.conf中 配置文件 設置了配置文件后啟動時以自定義的配置文件啟動:...
    AkaTBS閱讀 1,144評論 0 6
  • 個人入門學習用筆記、不過多作為參考依據。如有錯誤歡迎斧正 目錄 簡介安裝SchemaSchema嵌套官網示例真·M...
    kirito_song閱讀 429評論 0 18
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,625評論 18 399
  • 這部分主要是開源Java EE框架方面的內容,包括Hibernate、MyBatis、Spring、Spring ...
    雜貨鋪老板閱讀 1,554評論 0 2
  • 整個11月不知道自己是怎么過來的:趕上工作更換崗位,新歡舊愛兩頭燒;還作死給自己報名了微課:Angie的時間管理特...
    KIS寧閱讀 824評論 2 3

友情鏈接更多精彩內容