国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

(轉)Mongoose學習參考文檔

Sleepy / 938人閱讀

摘要:轉自一快速通道名詞解釋一種以文件形式存儲的數據庫模型骨架,不具備數據庫的操作能力由發布生成的模型,具有抽象屬性和行為的數據庫操作對由創建的實體,他的操作也會影響數據庫注意本學習文檔采用嚴格命名方式來區別不同對象,例如的文本屬性的數據庫模型實

轉自 https://cnodejs.org/topic/504...

一、快速通道 1.1 名詞解釋

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

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

Entity : 由Model創建的實體,他的操作也會影響數據庫

注意:

1.本學習文檔采用嚴格命名方式來區別不同對象,例如:

var PersonSchema;   //Person的文本屬性
var PersonModel;    //Person的數據庫模型
var PersonEntity;   //Person實體

2.Schema、Model、Entity的關系請牢記,Schema生成Model,Model創造Entity,Model和Entity都可對數據庫操作造成影響,但Model比Entity更具操作性。

1.2 準備工作

1.首先你必須安裝MongoDB和NodeJS

2.在項目只能夠創建一個數據庫連接,如下:

var mongoose = require("mongoose");    //引用mongoose模塊
var db = mongoose.createConnection("localhost","test"); //創建一個數據庫連接

3.打開本機localhost的test數據庫時,我們可以監測是否有異常

db.on("error",console.error.bind(console,"連接錯誤:"));
db.once("open",function(){
  //一次打開記錄
});

注意:

成功開啟數據庫后,就可以執行數據庫相應操作,假設以下代碼都在回調中處理

4.定義一個Schema

var PersonSchema = new mongoose.Schema({
  name:String   //定義一個屬性name,類型為String
});

5.將該Schema發布為Model

var PersonModel = db.model("Person",PersonSchema);
//如果該Model已經發布,則可以直接通過名字索引到,如下:
//var PersonModel = db.model("Person");
//如果沒有發布,上一段代碼將會異常

6.用Model創建Entity

var personEntity = new PersonModel({name:"Krouky"});
//打印這個實體的名字看看
console.log(personEntity.name); //Krouky

7.我們甚至可以為此Schema創建方法

//為Schema模型追加speak方法
PersonSchema.methos.speak = function(){
  console.log("我的名字叫"+this.name);
}
var PersonModel = db.model("Person",PersonSchema);
var personEntity = new PersonModel({name:"Krouky"});
personEntity.speak();//我的名字叫Krouky

8.Entity是具有具體的數據庫操作CRUD的

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

9.如果要執行查詢,需要依賴Model,當然Entity也是可以做到的

PersonModel.find(function(err,persons){
  //查詢到的所有person
});

注意:

具體的如何配置Schema、Model以及Model和Entity的相關操作,我們會在后面進行

Model和Entity都有能影響數據庫的操作,但仍有區別,后面我們也會做解釋

二、新手指引

如果您還不清楚Mongoose是如何工作的,請參看第一章快速通道快速瀏覽他的用法吧

1. Schema——純潔的數據庫原型 1.1 什么是Schema

我理解Schema僅僅只是一斷代碼,他書寫完成后程序依然無法使用,更無法通往數據庫端
他僅僅只是數據庫模型在程序片段中的一種表現,或者是數據屬性模型

1.2 如何定義Schema
var BlogSchema = new Schema({
  title:String,
  author:String
  //new Schema()中傳入一個JSON對象,該對象形如 xxx:yyyy ,
  /xxx是一個字符串,定義了屬性,yyy是一個Schema.Type,定義了屬性類型
});
1.3 什么是Schema.Type

Schema.Type是由Mongoose內定的一些數據類型,基本數據類型都在其中,他也內置了一些Mongoose特有的Schema.Type。當然,你也可以自定義Schema.Type,只有滿足Schema.Type的類型才能定義在Schema內。

1.4 Schema.Types

NodeJS中的基本數據類型都屬于Schema.Type,另外Mongoose還定義了自己的類型

//舉例:
var ExampleSchema = new Schema({
  name:String,
  binary:Buffer,
  living:Boolean,
  updated:Date,
  age:Number,
  mixed:Schema.Types.Mixed, //該混合類型等同于nested
  _id:Schema.Types.ObjectId,  //主鍵
  _fk:Schema.Types.ObjectId,  //外鍵
  array:[],
  arrOfString:[String],
  arrOfNumber:[Number],
  arrOfDate:[Date],
  arrOfBuffer:[Buffer],
  arrOfBoolean:[Boolean],
  arrOfMixed:[Schema.Types.Mixed],
  arrOfObjectId:[Schema.Types.ObjectId]
  nested:{
    stuff:String,
  }
});
1.5 關于Buffer

Buffer和ArrayBuffer是Nodejs兩種隱藏的對象,相關內容請查看NodeJS-API

1.6 關于Mixed

Schema.Types.Mixed是Mongoose定義個混合類型,該混合類型如果未定義具體形式。因此,如果定義具體內容,就直接使用{}來定義,以下兩句等價

var AnySchema = new Schema({any:{}});
var AnySchema = new Schema({any:Schema.Types.Mixed});

混合類型因為沒有特定約束,因此可以任意修改,一旦修改了原型,則必須調用markModified()

person.anything = {x:[3,4,{y:"change"}]}
person.markModified("anything");//傳入anything,表示該屬性類型發生變化
person.save();
1.7 關于ObjectId

主鍵,一種特殊而且非常重要的類型,每個Schema都會默認配置這個屬性,屬性名為_id,除非自己定義,方可覆蓋

var mongoose = require("mongoose");
var ObjectId = mongoose.Schema.Types.ObjectId;
var StudentSchema = new Schema({}); //默認會有_id:ObjectId
var TeacherSchema = new Schema({id:ObjectId});//只有id:ObjectId

該類型的值由系統自己生成,從某種意義上幾乎不會重復,生成過程比較復雜,有興趣的朋友可以查看源碼。

1.8 關于Array

Array在JavaScript編程語言中并不是數組,而是集合,因此里面可以存入不同的值,以下代碼等價:

var ExampleSchema1 = new Schema({array:[]});
var ExampleSchema2 = new Schema({array:Array});
var ExampleSchema3 = new Schema({array:[Schema.Types.Mixed]});
var ExampleSchema4 = new Schema({array:[{}]});
1.9 附言

Schema不僅定義了文檔結構和使用性能,還可以有擴展插件、實例方法、靜態方法、復合索引、文檔生命周期鉤子

Schema可以定義插件,并且插件具有良好的可拔插性,請有興趣的讀者繼續往后閱讀或者查閱官方資料。

2. Schema的擴展 2.1 實例方法

有的時候,我們創造的Schema不僅要為后面的Model和Entity提供公共的屬性,還要提供公共的方法。

下面例子比快速通道的例子更加高級,可以進行高級擴展:

var PersonSchema = new Schema({name:String,type:String});
//查詢類似數據
PersonSchema.methods.findSimilarTypes = function(cb){
  return this.model("Person").find({type:this.type},cb);
}

使用如下:

var PersonModel = mongoose.model("Person",PersonSchema);
var krouky = new PersonSchema({name:"krouky",type:"前端工程師"});
krouky.findSimilarTypes(function(err,persons){
  //persons中就能查詢到其他前端工程師
});
2.2 靜態方法

靜態方法在Model層就能使用,如下:

PersonSchema.statics.findByName = function(name,cb){

this.find({name:new RegExp(name,"i"),cb});

}
var PersonModel = mongoose.model("Person",PersonSchema);
PersonModel.findByName("krouky",function(err,persons){

//找到所有名字叫krouky的人

});

2.3 索引

索引或者復合索引能讓搜索更加高效,默認索引就是主鍵索引ObjectId,屬性名為_id, 索引會作為一個專題來講解

2.4 虛擬屬性

Schema中如果定義了虛擬屬性,那么該屬性將不寫入數據庫,例如:

var PersonSchema = new Schema({
  name:{
    first:String,
    last:String
  }
});
var PersonModel = mongoose.model("Person",PersonSchema);
var krouky = new PersonModel({
  name:{first:"krouky",last:"han"}
});

如果每次想使用全名就得這樣

console.log(krouky.name.first + " " + krouky.name.last);

顯然這是很麻煩的,我們可以定義虛擬屬性:

PersonSchema.virtual("name.full").get(function(){
  return this.name.first + " " + this.name.last;
});

那么就能用krouky.name.full來調用全名了,反之如果知道full,也可以反解first和last屬性

PersonSchema.virtual("name.full").set(function(name){
  var split = name.split(" ");
  this.name.first = split[0];
  this.name.last = split[1];
});
var PersonModel = mongoose.model("Person",PersonSchema);
var krouky = new PersonModel({});
krouky.name.full = "krouky han";//會被自動分解
console.log(krouky.name.first);//krouky
2.5 配置項

在使用new Schema(config)時,我們可以追加一個參數options來配置Schema的配置,形如:

var ExampleSchema = new Schema(config,options);

或者使用

var ExampleSchema = new Schema(config);
ExampleSchema.set(option,value);

可供配置項有:safe、strict、capped、versionKey、autoIndex

2.5.1 safe——安全屬性(默認安全)

一般可做如下配置:

new Schema({...},{safe:true});

當然我們也可以這樣

new Schema({...},{safe:{j:1,w:2,wtimeout:10000}});

j表示做1份日志,w表示做2個副本(尚不明確),超時時間10秒

2.5.2 strict——嚴格配置(默認啟用)

確保Entity的值存入數據庫前會被自動驗證,如果你沒有充足的理由,請不要停用,例子:

var ThingSchema = new Schema({a:String});
var ThingModel = db.model("Thing",SchemaSchema);
var thing = new Thing({iAmNotInTheThingSchema:true});
thing.save();//iAmNotInTheThingSchema這個屬性將無法被存儲

如果取消嚴格選項,iAmNotInTheThingSchema將會被存入數據庫

該選項也可以在構造實例時使用,例如:

var ThingModel = db.model("Thing");
var thing1 = new ThingModel(doc,true);  //啟用嚴格
var thing2 = new ThingModel(doc,false); //禁用嚴格

注意:

strict也可以設置為throw,表示出現問題將會拋出錯誤

2.5.3 shardKey

需要mongodb做分布式,才會使用該屬性

2.5.4 capped——上限設置

如果有數據庫的批量操作,該屬性能限制一次操作的量,例如:

new Schema({...},{capped:1024});  //一次操作上線1024條數據

當然該參數也可是JSON對象,包含size、max、autiIndexId屬性

new Schema({...},{capped:{size:1024,max:100,autoIndexId:true}});
2.5.5 versionKey——版本鎖

版本鎖是Mongoose默認配置(__v屬性)的,如果你想自己定制,如下:

new Schema({...},{versionKey:"__someElse"});

此時存入數據庫的版本鎖就不是__v屬性,而是__someElse,相當于是給版本鎖取名字。

具體怎么存入都是由Mongoose和MongoDB自己決定,當然,這個屬性你也可以去除

new Schema({...},{versionKey:false});
除非你知道你在做什么,并且你知道這樣做的后果

2.5.6 autoIndex——自動索引

該內容將在索引章節多帶帶講解

3. Documents

Document是與MongoDB文檔一一對應的模型,Document可等同于Entity,具有屬性和操作性

注意:

Document的`CRUD都必須經過嚴格驗證的,參看2.5.2 Schema的strict嚴格配置

3.1 查詢

查詢內容過多,專題講解

3.2 更新

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

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第一個參數是查詢條件,第二個參數是更新的對象,但不能更新主鍵,這就是為什么要刪除主鍵的原因。

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

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

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

Person.findByIdAndUpdate(_id,{$set:{name:"MDragon"}},function(err,person){
  console.log(person.name); //MDragon
});

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

3.3 新增

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

//使用Entity來增加一條數據
var krouky = new PersonModel({name:"krouky"});
krouky.save(callback);
//使用Model來增加一條數據
var MDragon = {name:"MDragon"};
PersonModel.create(MDragon,callback);

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

3.4 刪除

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

4.Sub Docs

如同SQL數據庫中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的操作都由父類去執行

var ParentModel = db.model("Parent",parentSchema);
var parent = new ParentModel({
  children2:[{name:"c1"},{name:"c2"}]
});
parent.children2[0].name = "d";
parent.save(callback);

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

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

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
});
4.1 查詢子文檔

如果children是parent的子文檔,可以通過如下方法查詢到children

var child = parent.children.id(id);
4.2 新增、刪除、更新

子文檔是父文檔的一個屬性,因此按照屬性的操作即可,不同的是在新增父類的時候,子文檔是會被先加入進去的。

如果ChildrenSchema是臨時的一個子文檔,不作為數據庫映射集合,可以這樣:

var ParentSchema = new Schema({
  children:{
    name:String
  }
});
//其實就是匿名混合模式
5.Model 5.1 什么是Model

Model模型,是經過Schema構造來的,除了Schema定義的數據庫骨架以外,還具有數據庫行為模型,他相當于管理數據庫屬性、行為的類

5.2 如何創建Model

你必須通過Schema來創建,如下:

//先創建Schema
var TankSchema = new Schema({
  name:"String",
  size:"String" 
});
//通過Schema創建Model
var TankModel = mongoose.model("Tank",TankSchema);
5.2 操作Model

該模型就能直接拿來操作,具體查看API,例如:

var tank = {"something",size:"small"};
TankModel.create(tank);

注意:

你可以使用Model來創建Entity,Entity實體是一個特有Model具體對象,但是他并不具備Model的方法,只能用自己的方法。

//通過Model創建Entity
var tankEntity = new TankModel("someother","size:big");
tankEntity.save();

6.Query

查詢是數據庫中運用最多也是最麻煩的地方,這里對Query解讀的并不完善,僅僅是自己的一點領悟而已。

6.1 查詢的方式

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

6.1.1 直接查詢

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

PersonModel.findOne({"name.last":"dragon"},"some select",function(err,person){
  //如果err==null,則person就能取到數據
});

具體的查詢參數,請查詢API

6.1.2 鏈式查詢

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

var query = PersonModel.findOne({"name.last":"dragon"});
query.select("some select");
query.exec(function(err,pserson){
//如果err==null,則person就能取到數據

});
這種方式相對直接查詢,分的比較明細,如果不帶callback,則返回query,query沒有執行的預編譯查詢語句,該query對象執行的方法都將返回自己,只有在執行exec方法時才執行查詢,而且必須有回調。

因為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);
7.Validation

數據的存儲是需要驗證的,不是什么數據都能往數據庫里丟或者顯示到客戶端的,數據的驗證需要記住以下規則:

驗證始終定義在SchemaType中
驗證是一個內部中間件
驗證是在一個Document被保存時默認啟用的,除非你關閉驗證
驗證是異步遞歸的,如果你的SubDoc驗證失敗,Document也將無法保存
驗證并不關心錯誤類型,而通過ValidationError這個對象可以訪問

7.1 驗證器

required 非空驗證
min/max 范圍驗證(邊值驗證)
enum/match 枚舉驗證/匹配驗證
validate 自定義驗證規則
以下是綜合案例:

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是一個驗證函數,err是驗證失敗的錯誤信息
  }
});
7.2 驗證失敗

如果驗證失敗,則會返回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屬性

8.Middleware中間件 8.1 什么是中間件

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

8.2 中間件的分類

中間件分為兩類

8.2.1 Serial串行

串行使用pre方法,執行下一個方法使用next調用

var schema = new Schema(...);
schema.pre("save",function(next){
  //做點什么
  next();
});
8.2.2 Parallel并行

并行提供更細粒度的操作

var schema = new Schema(...);
schema.pre("save",function(next,done){
  //下一個要執行的中間件并行執行
  next();
  doAsync(done);
});
8.3 中間件特點

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

8.4 使用范疇

復雜的驗證
刪除有主外關聯的doc
異步默認
某個特定動作觸發異步任務,例如觸發自定義事件和通知
例如,可以用來做自定義錯誤處理

schema.pre("save",function(next){
  var err = new Eerror("some err");
  next(err);
});
entity.save(function(err){
  console.log(err.message); //some err
});

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/18964.html

相關文章

  • mongoose 鏈接數據庫,增刪改查

    摘要:根據個人編碼習慣,僅供參考如中途看的有點蒙圈,可以轉到官網查看引入模塊連接數據庫鏈接狀態數據庫鏈接成功為了查看是否鏈接成功所以做一個回調創建模式對象例將賦值給變量創建對象官網創建通過來創建代表的是數據庫中的集合,通過才能對數據庫進行操作可在 根據個人編碼習慣,僅供參考 如中途看的有點蒙圈,可以轉到官網查看 引入模塊 var mongoose = require(mongoose); ...

    lanffy 評論0 收藏0
  • Node學習記錄: mongodb

    摘要:的邏輯結構是一種層次結構,主要由文檔集合數據庫這三部分組成的。文檔由鍵值對構成,像等,它是核心單元,的文檔,相當于關系數據庫中的一行記錄。我們以此為例看它如何使用真實項目中參考學習筆記之的使用入門教程的一些操作命令 showImg(https://segmentfault.com/img/bVN45N?w=1192&h=578); 簡介 在說MongoDB數據插入操作之前,我們先來簡單...

    zzzmh 評論0 收藏0
  • []mongodb中的populate方法

    摘要:使用可以實現在一個中填充其他的。表示關聯注意被關聯的的必須是和才有效。封裝了很多查詢的方法,使得對數據庫的操作變得簡單啦。這里分享一下方法用法。類型的時,格式如為表示不填充,為時表示填充。類型,可選,指定附加的查詢條件。 Mongoose 是 MongoDB 的 ODM(Object Document Mapper)。 什么是ODM? 其實和ORM(Object Relational...

    ranwu 評論0 收藏0
  • 前端學習資源整理

    稍微整理了一下自己平時看到的前端學習資源,分享給大家。 html MDN:Mozilla開發者網絡 SEO:前端開發中的SEO css 張鑫旭:張鑫旭的博客 css精靈圖:css精靈圖實踐 柵格系統:詳解CSS中的柵格系統 媒體查詢:css媒體查詢用法 rem布局:手機端頁面自適應布局 移動前端開發之viewport的深入理解:深入理解viewport 淘寶前端布局:手機淘寶移動端布局 fl...

    siberiawolf 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<