mongoose是nodeJS提供鏈接 mongodb的一個庫,相似於jquery和js的關係,對mongodb一些原生方法進行了封裝以及優化。簡單的說,Mongoose就是對node環境中MongoDB數據庫操做的封裝,一個對象模型工具,將數據庫中的數據轉換爲JavaScript對象以供咱們在應用中使用。html
npm install mongoose --save
複製代碼
const mongoose = require('mongoose'),
connection = mongoose.connect('mongodb://127.0.0.1:27017/wechatShop', {
useMongoClient: true
});
複製代碼
Mongoose的一切都始於一個Schema。每一個schema映射到MongoDB的集合(collection)和定義該集合(collection)中的文檔的形式。 Schemas不只定義了文檔和屬性的結構,還定義了文檔實例方法、靜態模型方法、複合索引和文檔被稱爲中間件的生命週期鉤子。node
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
}
});
複製代碼
使用咱們的schema定義,咱們須要將咱們的blogschema轉成咱們能夠用的模型。爲此,咱們經過mongoose.model(modelName, schema)。python
var Blog = mongoose.model('Blog', blogSchema);
複製代碼
模型的實例是文檔(documents)。文檔有許多本身內置的實例方法。咱們也能夠定義咱們本身的自定義文檔實例方法。mysql
var Blog = mongoose.model('Blog', blogSchema);
var blog = new Schema({ name: String, type: String });//模型實例
複製代碼
經常使用的內置實例方法有:jquery
remove、set、get、invalidate、populate、save等git
詳細api可查閱官方文檔內置的實例方法;github
下面咱們來講說自定義實例方法。自定義實例方法,就是對當前實例的methods擴展方法便可,以下所示:sql
animalSchema.methods.findSimilarTypes = function(cb) {
return this.model('Animal').find({ type: this.type }, cb);
};
複製代碼
經常使用的內置靜態方法有:mongodb
create、find、findOne等數據庫
給一個模型添加靜態方法的也是很簡單。繼續咱們的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);
});
複製代碼
您還能夠像實例方法那樣添加查詢輔助功能,這是,但對於mongoose的查詢。查詢輔助方法可讓你擴展mongoose鏈式查詢生成器API。
animalSchema.query.byName = function(name) {
return this.find({ name: new RegExp(name, 'i') });
};
var Animal = mongoose.model('Animal', animalSchema);
Animal.find().byName('fido').exec(function(err, animals) {
console.log(animals);
});
複製代碼
mongoose一樣也對索引作了處理,在mongoose中定義索引有兩種方法。
第一種:直接在schema裏面定義,以下所示
var User = mongoose.model('User', {
username: {
type: String,
index: true
},
password: String
})
複製代碼
第二種:統必定義索引
var User = mongoose.model('User', {
username: {
type: String
},
password: String
});
User.index({
username: 1 / -1 (正向和逆向)
})
複製代碼
關閉索引:
mongoose.connect('mongodb://user:pass@localhost:port/database', { config: { autoIndex: false } });
// or
mongoose.createConnection('mongodb://user:pass@localhost:port/database', { config: { autoIndex: false } });
// or
animalSchema.set('autoIndex', false);
// or
new Schema({..}, { autoIndex: false });
複製代碼
注意:索引濫用會致使很嚴重的性能問題,建議合理使用索引。
虛擬屬性 是文檔屬性,您能夠獲取和設置但不保存到MongoDB。用於格式化或組合字段,從而制定者去組成一個單一的值爲存儲多個值是有用的。
下面咱們先定義一個實例
// define a schema
var personSchema = new Schema({
name: {
first: String,
last: String
}
});
// compile our model
var Person = mongoose.model('Person', personSchema);
// create a document
var bad = new Person({
name: { first: 'Walter', last: 'White' }
});
複製代碼
假設咱們想打印bad的全名。咱們能夠這樣作:
console.log(bad.name.first + ' ' + bad.name.last); // Walter White
複製代碼
或者咱們能夠在personschema定義 虛擬屬性的getter ,這樣咱們不須要每次寫出這個字符串的拼接:
personSchema.virtual('name.full').get(function () {
return this.name.first + ' ' + this.name.last;
});
console.log('%s is insane', bad.name.full); // Walter White is insane
複製代碼
注意,這裏的虛擬屬性並無存入數據庫,因此若是是直接獲取,是獲取不到值的。
在咱們進入驗證語法的細節以前,請記住如下的規則:
驗證是在SchemaType定義
驗證是中間件。Mongoose寄存器驗證做爲pre('save')鉤子在每一個模式默認狀況下。
你能夠手動使用doc運行驗證。validate(callback) or doc.validateSync()。
驗證程序不運行在未定義的值上。惟一的例外是required驗證器。
驗證異步遞歸;當你調用Model#save,子文檔驗證也能夠執行。若是出現錯誤,你的 Model#save回調接收它。
驗證是可定製的。
var schema = new Schema({
name: {
type: String,
required: true
}
});
var Cat = db.model('Cat', schema);
// This cat has no name :(
var cat = new Cat();
cat.save(function(error) {
assert.equal(error.errors['name'].message,
'Path `name` is required.');
error = cat.validateSync();
assert.equal(error.errors['name'].message,
'Path `name` is required.');
});
複製代碼
全部的schematypes有內置的require驗證器。所需的驗證器使用SchemaType的checkrequired()函數肯定的值知足所需的驗證器。
數值( Numbers )有最大(man)和最小(min)的驗證器。
字符串(String)有枚舉,match,maxLength和minLength驗證器。
每個上述的驗證連接提供更多的信息關於如何使他們和自定義錯誤信息。
var breakfastSchema = new Schema({
eggs: {
type: Number,
min: [6, 'Too few eggs'],
max: 12
},
bacon: {
type: Number,
required: [true, 'Why no bacon?']
},
drink: {
type: String,
enum: ['Coffee', 'Tea']
}
});
var Breakfast = db.model('Breakfast', breakfastSchema);
var badBreakfast = new Breakfast({
eggs: 2,
bacon: 0,
drink: 'Milk'
});
var error = badBreakfast.validateSync();
assert.equal(error.errors['eggs'].message,
'Too few eggs');
assert.ok(!error.errors['bacon']);
assert.equal(error.errors['drink'].message,
'`Milk` is not a valid enum value for path `drink`.');
badBreakfast.bacon = null;
error = badBreakfast.validateSync();
assert.equal(error.errors['bacon'].message, 'Why no bacon?');
複製代碼
若是內置驗證器是不夠的話,你能夠自定義驗證器來適應你的需求。
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!'
},
required: [true, 'User phone number required']
}
});
複製代碼
驗證失敗後Errors返回一個錯誤的對象其實是validatorerror對象。每一個ValidatorError有kind, path, value, and message屬性。
var Person = db.model('Person', personSchema);
var person = new Person();
var error = person.validateSync();
複製代碼
若是你使用過mysql,確定用過join,用來聯表查詢,但mongoose中並無join,不過它提供了一種更方便快捷的辦法,Population。
首先定義兩個model。
var User = mongoose.model('User', {
username: String,
password: String
})
var News = mongoose.model('News', {
title: String,
author: {
type: mongoose.Schema.ObjectId,
ref: 'User'
}
});
複製代碼
而後添加數據
User.create({username:'ck',username:'滴滴'},function(err, data){
console.log(data)
News.create({title:'title',author:data},function(){
})
})
複製代碼
打印查詢結果到控制檯
News.findOne().populate('author','username').exec(function(err, doc){
console.log('==============',err, doc)
// ============== null { _id: 5a41d2e16f78a43c5873fe03,
// title: 'title',
// author: { _id: 5a41d2e16f78a43c5873fe02, username: 'ck'
// },
// __v: 0 }
})
複製代碼