1. 程式人生 > >mongoose中的Schema和Model

mongoose中的Schema和Model

Schema

Schema主要用於定義MongoDB中集合Collection裡文件document的結構,可以理解為mongoose對錶結構的定義(不僅僅可以定義文件的結構和屬性,還可以定義文件的例項方法、靜態模型方法、複合索引等),每個schema會對映到mongodb中的一個collection,schema不具備操作資料庫的能力

 定義Schema非常簡單,指定欄位名和型別即可,支援的型別包括以下8種

String      字串
Number      數字    
Date        日期
Buffer      二進位制
Boolean     布林值
Mixed       混合型別
ObjectId    物件ID    
Array       陣列

 通過mongoose.Schema來呼叫Schema,然後使用new方法來建立schema

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var mySchema = 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
  }
});

 注意 建立Schema物件時,宣告欄位型別有兩種方法,一種是首字母大寫的欄位型別,另一種是引號包含的小寫欄位型別

var mySchema = new Schema({title:String, author:String});
//或者 
var mySchema = new Schema({title:'string', author:'string'});

 如果需要在Schema定義後新增其他欄位,可以使用add()方法

var MySchema = new Schema;
MySchema.add({ name: 'string', color: 'string', price: 'number' });

Model

 Model是由Schema編譯而成的假想(fancy)構造器,具有抽象屬性和行為。Model的每一個例項(instance)就是一個document,document可以儲存到資料庫和對資料庫進行操作。簡單說就是model是由schema生成的模型,可以對資料庫的操作。

  使用model()方法,將Schema編譯為Model。model()方法的第一個引數是模型名稱

mongoose.model(`文件名稱`, Schema)

  注意 一定要將model()方法的第一個引數和其返回值設定為相同的值,否則會出現不可預知的結果

  Mongoose會將集合名稱設定為模型名稱的小寫版。如果名稱的最後一個字元是字母,則會變成複數;如果名稱的最後一個字元是數字,則不變;如果模型名稱為"MyModel",則集合名稱為"mymodels";如果模型名稱為"Model1",則集合名稱為"model1"

var schema = new mongoose.Schema({ num:Number, name: String, size: String});
var MyModel = mongoose.model('MyModel', schema);

【例項化文件document】

  通過對原型Model1使用new方法,例項化出文件document物件

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:[email protected]/db1", function(err) {
    if(err){
        console.log('連線失敗');
    }else{
        console.log('連線成功');
        var schema = new mongoose.Schema({ num:Number, name: String, size: String});
        var MyModel = mongoose.model('MyModel', schema);
        var doc1 = new MyModel({ size: 'small' });
        console.log(doc1.size);//'small'
    }
});

【文件儲存】

  通過new Model1()建立的文件doc1,必須通過save()方法,才能將建立的文件儲存到資料庫的集合中,集合名稱為模型名稱的小寫複數版

  回撥函式是可選項,第一個引數為err,第二個引數為儲存的文件物件

save(function (err, doc) {})
var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:[email protected]/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ num:Number, name: String, size: String });
        var MyModel = mongoose.model('MyModel', schema);
        var doc1 = new MyModel({ size: 'small' });
        doc1.save(function (err,doc) {
        //{ __v: 0, size: 'small', _id: 5970daba61162662b45a24a1 }
          console.log(doc);
        })
    }
});

  由下圖所示,db1資料庫中的集合名稱為mymodels,裡面有一個{size:"small"}的文件

clipboard.png

自定義方法 【例項方法】

  Model的例項是document,內建例項方法有很多,如 save,可以通過Schema物件的methods屬性給例項自定義擴充套件方法

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:[email protected]/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ num:Number, name: String, size: String });        
        schema.methods.findSimilarSizes = function(cb){
            return this.model('MyModel').find({size:this.size},cb);
        }
        var MyModel = mongoose.model('MyModel', schema);
        var doc1 = new MyModel({ name:'doc1', size: 'small' });
        var doc2 = new MyModel({ name:'doc2', size: 'small' });
        var doc3 = new MyModel({ name:'doc3', size: 'big' });
        doc1.save();
        doc2.save();
        doc3.save();
        setTimeout(function(){
            doc1.findSimilarSizes(function(err,docs){
                docs.forEach(function(item,index,arr){
                    //doc1
                    //doc2
                     console.log(item.name)        
                })
            })  
        },0)  
    }
});

【靜態方法】

  通過Schema物件的statics屬性給 Model 新增靜態方法

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:[email protected]/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ num:Number, name: String, size: String });        
        schema.statics.findByName = function(name,cb){
            return this.find({name: new RegExp(name,'i')},cb);
        }
        var MyModel = mongoose.model('MyModel', schema);
        var doc1 = new MyModel({ name:'doc1', size: 'small' });
        var doc2 = new MyModel({ name:'doc2', size: 'small' });
        var doc3 = new MyModel({ name:'doc3', size: 'big' });
        doc1.save();
        doc2.save();
        doc3.save();
        setTimeout(function(){
            MyModel.findByName('doc1',function(err,docs){
                //[ { _id: 5971e68f4f4216605880dca2,name: 'doc1',size: 'small',__v: 0 } ]
                console.log(docs);
            })  
        },0)  
    }
});

  由上所示,例項方法和靜態方法的區別在於,靜態方法是通過Schema物件的statics屬性給model新增方法,例項方法是通過Schema物件的methods是給document新增方法

【Methods 和 Statics 的區別】

statics是給model新增方法,methods是給例項(instance)新增方法。methods和statics的區別

//module.exports = mongoose.model(`Article`, ArticleSchema )
//將article的model儲存為檔案 article.js

const Article = require('../models/article')

// statics
Article.staticFunc ()

//methods
const article = new Article(arguments)
article.methodFunc()

【查詢方法】

  通過schema物件的query屬性,給model新增查詢方法

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:[email protected]/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ age:Number, name: String});        
        schema.query.byName = function(name){
            return this.find({name: new RegExp(name)});
        }
        var temp = mongoose.model('temp', schema);   
        temp.find().byName('huo').exec(function(err,docs){
            //[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 },
            // { _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 } ]
            console.log(docs);
        })  

    }           
});