Mongoose 是 MongoDB 的 ODM(Object Document Mapper)。
什麼是ODM? 其實和ORM(Object Relational Mapper)是同類型的工具。都是將數據庫的數據轉化爲代碼對象的庫,使用轉化後的對象能夠直接對數據庫的數據進行CRUD(增刪改查)。
MongoDB 是文檔型數據庫(Document Database),不是關係型數據庫(Relational Database)。而Mongoose能夠將 MongonDB 數據庫存儲的文檔(documents)轉化爲 javascript 對象,而後能夠直接進行數據的增刪改查。javascript
由於MongoDB是文檔型數據庫,因此它沒有關係型數據庫[joins](http://zh.wikipedia.org/wiki/%E8%BF%9E%E6%8E%A5_(SQL)(數據庫的兩張表經過"外鍵",創建鏈接關係。) 特性。也就是在創建數據的關聯時會比較麻煩。爲了解決這個問題,Mongoose封裝了一個Population功能。使用Population能夠實如今一個 document 中填充其餘 collection(s) 的 document(s)。java
在定義Schema的時候,若是設置某個 field 關聯另外一個Schema,那麼在獲取 document 的時候就能夠使用 Population 功能經過關聯Schema的 field 找到關聯的另外一個 document,而且用被關聯 document 的內容替換掉原來關聯字段(field)的內容。mongodb
接下來分享下:Query#populate Model#populate Document#populate的用法數據庫
先創建三個Schema和Model:數組
var mongoose = require('mongoose'); var Schema = mongoose.Schema; var UserSchema = new Schema({ name : { type: String, unique: true }, posts : [{ type: Schema.Types.ObjectId, ref: 'Post' }] }); var User = mongoose.model('User', UserSchema); var PostSchema = new Schema({ poster : { type: Schema.Types.ObjectId, ref: 'User' }, comments : [{ type: Schema.Types.ObjectId, ref: 'Comment' }], title : String, content : String }); var Post = mongoose.model('Post', PostSchema); var CommentSchema = new Schema({ post : { type: Schema.Types.ObjectId, ref: "Post" }, commenter : { type: Schema.Types.ObjectId, ref: 'User' }, content : String }); var Comment = mongoose.model('Comment', CommentSchema);
在上述的例子中,建立了三個 Models:User,Post,Comment。
User 的屬性 posts,對應是一個 ObjectId 的數組。ref表示關聯Post(注意: 被關聯的model的 type 必須是ObjectId, Number, String, 和 Buffer 纔有效)。
Post的屬性 poster 和 comments 分別關聯User和Comment。
Comment的屬性 post 和 commenter 分別關聯Post和User。
三個 Models 的關係:一個 user--has many-->post。一個 post--has one-->user,has many-->comment。一個 comment--has one-->post 和 user。app
// 鏈接數據庫
mongoose.connect('mongodb://localhost/population-test', function (err){
if (err) throw err;
createData();
});mongoose
function createData() {工具
var userIds = [new ObjectId, new ObjectId, new ObjectId]; var postIds = [new ObjectId, new ObjectId, new ObjectId]; var commentIds = [new ObjectId, new ObjectId, new ObjectId]; var users = []; var posts = []; var comments = []; users.push({ _id : userIds[0], name : 'aikin', posts : [postIds[0]] }); users.push({ _id : userIds[1], name : 'luna', posts : [postIds[1]] }); users.push({ _id : userIds[2], name : 'luajin', posts : [postIds[2]] }); posts.push({ _id : postIds[0], title : 'post-by-aikin', poster : userIds[0], comments : [commentIds[0]] }); posts.push({ _id : postIds[1], title : 'post-by-luna', poster : userIds[1], comments : [commentIds[1]] }); posts.push({ _id : postIds[2], title : 'post-by-luajin', poster : userIds[2], comments : [commentIds[2]] }); comments.push({ _id : commentIds[0], content : 'comment-by-luna', commenter : userIds[1], post : postIds[0] }); comments.push({ _id : commentIds[1], content : 'comment-by-luajin', commenter : userIds[2], post : postIds[1] }); comments.push({ _id : commentIds[2], content : 'comment-by-aikin', commenter : userIds[1], post : postIds[2] }); User.create(users, function(err, docs) { Post.create(posts, function(err, docs) { Comment.create(comments, function(err, docs) { }); }); });
}post
什麼Query? Query(查詢),能夠快速和簡單的從MongooDB查找出相應的 document(s)。 Mongoose 封裝了不少查詢的方法,使得對數據庫的操做變得簡單啦。這裏分享一下populate方法用法。ui
語法:
Query.populate(path, [select], [model], [match], [options])
參數:
path
類型:String或Object。
String類型的時, 指定要填充的關聯字段,要填充多個關聯字段能夠以空格分隔。
Object類型的時,就是把 populate 的參數封裝到一個對象裏。固然也能夠是個數組。下面的例子中將會實現。
select
類型:Object或String,可選,指定填充 document 中的哪些字段。
Object類型的時,格式如:{name: 1, _id: 0},爲0表示不填充,爲1時表示填充。
String類型的時,格式如:"name -_id",用空格分隔字段,在字段名前加上-表示不填充。詳細語法介紹query-select
model
類型:Model,可選,指定關聯字段的 model,若是沒有指定就會使用Schema的ref。
match
類型:Object,可選,指定附加的查詢條件。
options
類型:Object,可選,指定附加的其餘查詢選項,如排序以及條數限制等等。
填充User的posts字段:
全選複製放進筆記User.findOne({name: 'aikin'})
.exec(function(err, doc) {
var opts = [{ path : 'posts', select : 'title' }]; doc.populate(opts, function(err, populatedDoc) { console.log(populatedDoc.posts[0].title); // post-by-aikin }); });