Mongoose學習

Mongoose學習javascript

1. 說明

由於網上關於mongoose的文檔有不少,可是都是分塊的沒有系統的總結,因此我總結網上的文章理出來一條思路,文檔中的不少內容都是從其餘文章中複製過來的,只做爲我的知識的學習,不會用於商用,在文章多處我也註明了出處html

2. Mongoose介紹

2.1. 什麼是MongoDB?

MongoDB是一個開源的NoSQL數據庫,相比MySQL那樣的關係型數據庫,它更爲輕巧、靈活,很是適合在數據規模很大、事務性不強的場合下使用。java

2.2. 什麼是Mongoose?

Mongoose是封裝了MongoDB的操做的一個對象模型庫,爲nodejs而生。就好像咱們嫌原生javascript難寫,代碼量多,因而用jQuery庫同樣,由於MongoDB的操做接口複雜,不人性,因此有了Mongoose。這個庫徹底是可選的。node

2.3. 名詞解釋

  • Schema:一種以文件形式存儲的數據庫模型骨架,不具有數據庫的操做能力
  • Model:由Schema發佈生成的模型,具備抽象屬性和行爲的數據庫操做對
  • Entity:由Model建立的實體,他的操做也會影響數據庫

2.4. 注意

  • Schema、Model、Entity的關係請牢記,Schema生成Model,Model創造Entity,Model和Entity均可對數據庫操做形成影響,但Model比Entity更具操做性。

2.5. 學習文章

3. Schema

3.1. Schema.Type

  • 內置類型git

    String Number Date Buffer Boolean Mixed Objectid Arraygithub

  • 用法實例數據庫

var schema = new Schema({
  name:    String,
  binary:  Buffer,
  living:  Boolean,
  updated: { type: Date, default: Date.now },
  age:     { type: Number, min: 18, max: 65 },
  mixed:   Schema.Types.Mixed,
  _someId: Schema.Types.ObjectId,
  array:      [],
  ofString:   [String],
  ofNumber:   [Number],
  ofDates:    [Date],
  ofBuffer:   [Buffer],
  ofBoolean:  [Boolean],
  ofMixed:    [Schema.Types.Mixed],
  ofObjectId: [Schema.Types.ObjectId],
  nested: {
    stuff: { type: String, lowercase: true, trim: true }
  }
})

// example use

var Thing = mongoose.model('Thing', schema);

var m = new Thing;
m.name = 'Statue of Liberty';
m.age = 125;
m.updated = new Date;
m.binary = new Buffer(0);
m.living = false;
m.mixed = { any: { thing: 'i want' } };
m.markModified('mixed');
m._someId = new mongoose.Types.ObjectId;
m.array.push(1);
m.ofString.push("strings!");
m.ofNumber.unshift(1,2,3,4);
m.ofDates.addToSet(new Date);
m.ofBuffer.pop();
m.ofMixed = [1, [], 'three', { four: 5 }];
m.nested.stuff = 'good';
m.save(callback);

3.2. Validation(驗證)

  • Validation是在SchemaType定義
  • Validation是中間件的內部組件
  • Validation發生在document試圖在默認值應用以後保存的時候。
  • Validation不在未定義的值運行,惟一例外是必要的驗證器。
  • Validation是異步遞歸的,當你調用Model#save,子文檔驗證也會執行。若是發生錯誤,Model#save回調會接收它。
  • 驗證支持徹底定製

3.2.1. 內置校驗器

  • 全部SchemaTypes都有內置requiredValidation。
  • 數字有最大值和最小值驗證。
  • 字符串有枚舉、匹配、最大長度和最小長度驗證。
  • 用法實例
var schema = new mongoose.Schema({
    name:{
        type:'String',
        required: true,
        maxlength: 10,
        match: /^a/   
    },
    date: {
        type: Date,
        default: Date.now
    },
    age:{
        type:'Number',
        min:18,       //年齡最小18
        max:120     //年齡最大120
    },
    city:{
        type:'String',
        enum:['北京','上海']  //只能是北京、上海人
    },
});

3.2.2. 自定義校驗器

  • 若是內置驗證器不夠,validation可以徹底能夠知足你的需求
  • 用法實例
var userSchema = new Schema({
  phone: {
    type: String,
    validate: {
      validator: function(v) {
        return /d{3}-d{3}-d{4}/.test(v);
      },
      message: '{VALUE} is not a valid phone number!'
    }
  }
});

var User = mongoose.model('user', userSchema);

var u = new User();

u.phone = '555.0123';
// Prints "ValidationError: 555.0123 is not a valid phone number!"
console.log(u.validateSync().toString());

u.phone = '201-555-0123';
// Prints undefined - validation succeeded!
console.log(u.validateSync());

3.3. 建立

  • 語法:mongoose.model(modelName, schema)
  • 用法實例
var Blog = mongoose.model('Blog', blogSchema)

3.4. 實例方法

  • 用法實例
// 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
});

3.5. 靜態方法

  • 用法實例
// 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);
});

3.6. 索引

  • MongoDB支持二級索引。在mongoose,at the path level或schema層次定義Schema的索引。當建立複合索引時,在shema定義索引是必要的。
var animalSchema = new Schema({
  name: String,
  type: String,
  tags: { type: [String], index: true } // field level
});

animalSchema.index({ name: 1, type: -1 }); // schema level
  • 當程序啓動時,Mongoose爲每一個在schema定義的索引自動地調用ensureIndex 。Mongoose會連續爲每一個索引調用ensureIndex,當全部ensureIndex調用成功或發生錯誤在model發出index事件。建議在生產中禁止這種行爲由於索引建立可以致使顯著的性能影響。經過給schema設置autoIndex選項爲false來禁用行爲,或者在connection全局設置選項config.autoIndex爲false。
animalSchema.set('autoIndex', false);
// or
new Schema({..}, { autoIndex: false });

3.7. Virtuals(虛擬屬性)

  • virtual是你能 get 和 set 但不能保存到MongoDB的document屬性。getter用於格式化或符合的field,而setter用於de-composing一個單值到多值存儲。
  • 用法實例
// define a schema
var personSchema = new Schema({
  name: {
    first: String,
    last: String
  }
});

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

// compile our model
var Person = mongoose.model('Person', personSchema);

// create a document
var bad = new Person({
    name: { first: 'Walter', last: 'White' }
});

console.log('%s is insane', bad.name.full); // Walter White is insane
bad.name.full = 'Breaking Bad';

personSchema.virtual('name.full').set(function (name) {
  var split = name.split(' ');
  this.name.first = split[0];
  this.name.last = split[1];
});

...

mad.name.full = 'Breaking Bad';
console.log(mad.name.first); // Breaking
console.log(mad.name.last);  // Bad

3.8. option(擴展選項)

  • 用法實例
new Schema({..}, options);

// or

var schema = new Schema({..});
schema.set(option, value);

3.9. Middleware(中間件)

  • 中間件(也稱爲pre and post hook)是執行異步函數期間傳遞控制權的函數。中間件在schema級別上被指定並對於編寫插件很是有用

3.9.1. document中間件和query中間件

  • document中間件支持如下document函數promise

    • init
    • validate
    • save
    • remove
  • query中間件支持如下model和query函數app

    • count
    • find
    • findOne
    • findOneAndRemove
    • findOneAndUpdate
    • update
  • 注意:沒有對remove()的query hook,只有對document的。若是你設置了一個remove hook,執行myDoc.remove()時它會激活,而不是執行MyModel.remove()。

3.9.2. pre類型中間件

3.9.3. post類型中間件

3.10. Plugins(插件)

  • schema是可插入的,即,它們能夠應用預包裝的能力,從而擴展其功能。這是一個很是強大的功能。

4. Model

5. Document

5.1. Population(join)

  • http://www.cnblogs.com/surahe/p/5188211.html
  • population是自動將document中指定path替換爲其餘collection的document的過程。咱們能遷移document、多個document、簡單對象、多個簡單對象或者是查詢返回的全部對象。

5.2. Sub-Docs(子文檔)

6. CURD

6.1. 鏈接

var mongoose = require('mongoose');    //引用mongoose模塊
var db = mongoose.createConnection('localhost','test'); //建立一個數據庫鏈接
  • 打開本機localhost的test數據庫時,咱們能夠監測是否有異常
db.on('error',console.error.bind(console,'鏈接錯誤:'));
db.once('open',function(){
  //一次打開記錄
});

6.2. 建立

6.2.1. document保存

var Tank = mongoose.model('Tank', yourSchema);

var small = new Tank({ size: 'small' });
small.save(function (err) {
  if (err) return handleError(err);
  // saved!
})

6.2.2. model保存

  • 語法

  • 該方法既能夠存儲一條數據也能夠存儲多條數據
  • 若是有回調函數,那麼在存儲多條數據的時候若是有一條報錯了,那麼不會走promise的then方法,可是其餘沒有報錯的數據已經被插入了
  • 若是沒有回調函數,那麼在存儲多條數據的時候若是有一條報錯了,那麼會走promise的then方法,可是其餘沒有報錯的數據已經被插入了
Model.create({ size: 'small' }, function (err, doc) {
  if (err) return handleError(err);
  // saved!
})

const promise= Model.create(Doc)
promise.then(function (result) {
    console.log(1111111111)
    console.log(result)
},function (err) {
    console.log(2222222222)
    console.log(err)
})

6.3. 修改

6.3.1. 修改不返回document

  • 語法:Model.update(conditions, doc, [options], [callback])
  • 用法實例
Tank.update({ _id: id }, { $set: { size: 'large' }}, function (err, raw) {
    if (err) return handleError(err);
    console.log('The raw response from Mongo was ', raw);
});

6.3.2. 修改返回document

  • 寫法一
Tank.findById(id, function (err, tank) {
  if (err) return handleError(err);

  tank.size = 'large';
  tank.save(function (err) {
    if (err) return handleError(err);
    res.send(tank);
  });
});
  • 寫法二(推薦)
Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
  if (err) return handleError(err);
  res.send(tank);
});

6.4. 刪除

Tank.remove({ size: 'large' }, function (err) {
  if (err) return handleError(err);
  // removed!
});

6.5. 查詢

6.5.1. 直接查詢

  • 在查詢時帶有回調函數的,稱之爲直接查詢,查詢的條件每每經過API來設定
  • 用法實例
PersonModel.findOne({'name.last':'dragon'},'some select',function(err,person){
      //若是err==null,則person就能取到數據
    });

6.5.2. 鏈式查詢

6.5.2.1. 寫法一

  • 這種方式相對直接查詢,分的比較明細,若是不帶callback,則返回query,query沒有執行的預編譯查詢語句,該query對象執行的方法都將返回本身,只有在執行exec方法時才執行查詢,並且必須有回調。
  • 用法實例
var query = PersonModel.findOne({'name.last':'dragon'});
     query.select('some select');
     query.exec(function(err,pserson){
     //若是err==null,則person就能取到數據
  });

 

6.5.2.2. 寫法一

  • 用法實例
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);

 

免責說明

一、本博客中的文章摘自網上的衆多博客,僅做爲本身知識的補充和整理,並分享給其餘須要的coder,不會用於商用。異步

二、由於不少博客的地址看完沒有及時作保存,因此不少不會在這裏標明出處,很是感謝各位大牛的分享,也但願你們理解。

相關文章
相關標籤/搜索