摘要:使用可以實現(xiàn)在一個中填充其他的。表示關(guān)聯(lián)注意被關(guān)聯(lián)的的必須是和才有效。類型的時,格式如為表示不填充,為時表示填充。以鍵值對的形式表示。回調(diào)函數(shù),接收兩個參數(shù),錯誤和填充完的。參考數(shù)據(jù)庫的最簡單實現(xiàn)使用之原文鏈接
Mongoose 是 MongoDB 的 ODM(Object Document Mapper)。
什么是ODM? 其實和ORM(Object Relational Mapper)是同類型的工具。都是將數(shù)據(jù)庫的數(shù)據(jù)轉(zhuǎn)化為代碼對象的庫,使用轉(zhuǎn)化后的對象可以直接對數(shù)據(jù)庫的數(shù)據(jù)進行CRUD(增刪改查)。
MongoDB 是文檔型數(shù)據(jù)庫(Document Database),不是關(guān)系型數(shù)據(jù)庫(Relational Database)。而Mongoose可以將 MongonDB 數(shù)據(jù)庫存儲的文檔(documents)轉(zhuǎn)化為 javascript 對象,然后可以直接進行數(shù)據(jù)的增刪改查。
因為MongoDB是文檔型數(shù)據(jù)庫,所以它沒有關(guān)系型數(shù)據(jù)庫joins(數(shù)據(jù)庫的兩張表通過"外鍵",建立連接關(guān)系。) 特性。也就是在建立數(shù)據(jù)的關(guān)聯(lián)時會比較麻煩。為了解決這個問題,Mongoose封裝了一個Population功能。使用Population可以實現(xiàn)在一個 document 中填充其他 collection(s) 的 document(s)。
在定義Schema的時候,如果設(shè)置某個 field 關(guān)聯(lián)另一個Schema,那么在獲取 document 的時候就可以使用 Population 功能通過關(guān)聯(lián)Schema的 field 找到關(guān)聯(lián)的另一個 document,并且用被關(guān)聯(lián) document 的內(nèi)容替換掉原來關(guān)聯(lián)字段(field)的內(nèi)容。
接下來分享下: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);
在上述的例子中,創(chuàng)建了三個 Models:User,Post,Comment。
User 的屬性 posts,對應(yīng)是一個 ObjectId 的數(shù)組。ref表示關(guān)聯(lián)Post(注意: 被關(guān)聯(lián)的model的 type 必須是 ObjectId, Number, String, 和 Buffer 才有效)。
Post的屬性 poster 和 comments 分別關(guān)聯(lián)User和Comment。
Comment的屬性 post 和 commenter 分別關(guān)聯(lián)Post和User。
三個 Models 的關(guān)系:一個 user--has many-->post。一個 post--has one-->user,has many-->comment。一個 comment--has one-->post 和 user。
創(chuàng)建一些數(shù)據(jù)到數(shù)據(jù)庫:
// 連接數(shù)據(jù)庫 mongoose.connect("mongodb://localhost/population-test", function (err){ if (err) throw err; createData(); }); 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) { }); }); }); }
數(shù)據(jù)的準備就緒后,接下來就是探索populate方法:
1. Query#populate什么Query? Query(查詢),可以快速和簡單的從MongooDB查找出相應(yīng)的 document(s)。 Mongoose 封裝了很多查詢的方法,使得對數(shù)據(jù)庫的操作變得簡單啦。這里分享一下populate方法用法。
語法:
**`Query.populate(path, [select], [model], [match], [options])`**參數(shù):
path
類型:String或Object。
String類型的時, 指定要填充的關(guān)聯(lián)字段,要填充多個關(guān)聯(lián)字段可以以空格分隔。
Object類型的時,就是把 populate 的參數(shù)封裝到一個對象里。當(dāng)然也可以是個數(shù)組。下面的例子中將會實現(xiàn)。
select
類型:Object或String,可選,指定填充 document 中的哪些字段。
Object類型的時,格式如:{name: 1, _id: 0},為0表示不填充,為1時表示填充。
String類型的時,格式如:"name -_id",用空格分隔字段,在字段名前加上-表示不填充。詳細語法介紹 query-select
model
類型:Model,可選,指定關(guān)聯(lián)字段的 model,如果沒有指定就會使用Schema的ref。
match
類型:Object,可選,指定附加的查詢條件。
options
類型:Object,可選,指定附加的其他查詢選項,如排序以及條數(shù)限制等等。
填充User的posts字段:
//填充所有 users 的 posts User.find() .populate("posts", "title", null, {sort: { title: -1 }}) .exec(function(err, docs) { console.log(docs[0].posts[0].title); // post-by-aikin }); //填充 user "luajin"的 posts User.findOne({name: "luajin"}) .populate({path: "posts", select: { title: 1 }, options: {sort: { title: -1 }}}) .exec(function(err, doc) { console.log(doc.posts[0].title); // post-by-luajin }); //這里的 populate 方法傳入的參數(shù)形式不同,其實實現(xiàn)的功能是一樣的,只是表示形式不一樣。
填充Post的poster和comments字段:
Post.findOne({title: "post-by-aikin"}) .populate("poster comments", "-_id") .exec(function(err, doc) { console.log(doc.poster.name); // aikin console.log(doc.poster._id); // undefined console.log(doc.comments[0].content); // comment-by-luna console.log(doc.comments[0]._id); // undefined }); Post.findOne({title: "post-by-aikin"}) .populate({path: "poster comments", select: "-_id"}) .exec(function(err, doc) { console.log(doc.poster.name); // aikin console.log(doc.poster._id); // undefined console.log(doc.comments[0].content); // comment-by-luna console.log(doc.comments[0]._id); // undefined }); //上兩種填充的方式實現(xiàn)的功能是一樣的。就是給 populate 方法的參數(shù)不同。 //這里要注意,當(dāng)兩個關(guān)聯(lián)的字段同時在一個 path 里面時, select 必須是 document(s) //具有的相同字段。 //如果想要給單個關(guān)聯(lián)的字段指定 select,可以傳入數(shù)組的參數(shù)。如下: Post.findOne({title: "post-by-aikin"}) .populate(["poster", "comments"]) .exec(function(err, doc) { console.log(doc.poster.name); // aikin console.log(doc.comments[0].content); // comment-by-luna }); Post.findOne({title: "post-by-aikin"}) .populate([ {path:"poster", select: "-_id"}, {path:"comments", select: "-content"} ]) .exec(function(err, doc) { console.log(doc.poster.name); // aikin console.log(doc.poster._id); // undefined console.log(doc.comments[0]._id); // 會打印出對應(yīng)的 comment id console.log(doc.comments[0].content); // undefined });2. Model#populate
Model(模型),是根據(jù)定義的 Schema 編譯成的抽象的構(gòu)造函數(shù)。models 的實例 documents,可以在數(shù)據(jù)庫中被保存和檢索。數(shù)據(jù)庫所有 document 的創(chuàng)建和檢索,都通過 models 處理。
語法:
**`Model.populate(docs, options, [cb(err,doc)])`**參數(shù):
docs
類型:Document或Array。單個需要被填充的 doucment 或者 document 的數(shù)組。
options
類型:Object。以鍵值對的形式表示。
keys:path select match model options,這些鍵對應(yīng)值的類型和功能,與上述Query#populate方法的參數(shù)相同。
[cb(err,doc)]
類型:Function,回調(diào)函數(shù),接收兩個參數(shù),錯誤err和填充完的doc(s)。
填充Post的poster和comments字段以及comments的commenter字段:
Post.find({title: "post-by-aikin"}) .populate("poster comments") .exec(function(err, docs) { var opts = [{ path : "comments.commenter", select : "name", model : "User" }]; Post.populate(docs, opts, function(err, populatedDocs) { console.log(populatedDocs[0].poster.name); // aikin console.log(populatedDocs[0].comments[0].commenter.name); // luna }); });3. Document#populate
Document,每個 document 都是其 Model 的一個實例,一對一的映射著 MongoDB 的 document。
語法:
**`Document.populate([path], [callback])`**參數(shù):
path
類型:String或Object。與上述Query#populate`方法的 path 參數(shù)相同。
callback
類型:Function。回調(diào)函數(shù),接收兩個參數(shù),錯誤err和填充完的doc(s)。
填充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 }); });
博文涉及的完整例子在 gist 上。(ps: gist 被已墻了。)
參考mongoose-api-docs
數(shù)據(jù)庫的最簡單實現(xiàn)
Mongoose 使用之 Population
原文鏈接
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/18758.html
摘要:使用可以實現(xiàn)在一個中填充其他的。表示關(guān)聯(lián)注意被關(guān)聯(lián)的的必須是和才有效。封裝了很多查詢的方法,使得對數(shù)據(jù)庫的操作變得簡單啦。這里分享一下方法用法。類型的時,格式如為表示不填充,為時表示填充。類型,可選,指定附加的查詢條件。 Mongoose 是 MongoDB 的 ODM(Object Document Mapper)。 什么是ODM? 其實和ORM(Object Relational...
摘要:比如,我們可以監(jiān)聽事件由實例發(fā)出,然后在任何瀏覽器中就是變化的時候都會得到通知,如下所示每一個作用域?qū)ο蠖紩羞@個方法,可以用來注冊一個作用域事件的偵聽器。這個函數(shù)所扮演的偵聽器在被調(diào)用時會有一個對象作為第一個參數(shù)。 上一篇:【譯】《精通使用AngularJS開發(fā)Web App》(二) 下一篇:【譯】《精通使用AngularJS開發(fā)Web App》(四) 書名:Mastering W...
摘要:往期回顧教程實現(xiàn)社交網(wǎng)絡(luò)可視化,看看你的人脈影響力如何轉(zhuǎn)載字概括精髓,必知必會例注意字歸納總結(jié)帶你做數(shù)據(jù)預(yù)處理新聞字張圖,一鍵生成炫酷的動態(tài)交互式圖表分享收藏點贊在看 今天分享幾個不為人知的pandas函數(shù),大家可能平時看到的不多,但是使用起來倒是非常的方便,也能夠幫助我們數(shù)據(jù)分析人員大...
摘要:更重要的是它將返回的字符串包裝成了對象,這在操作時要比直接使用字符串方便許多。今天就利用的官方文檔對它的標準操作進行簡單的分析。 NOSQL存儲作為一種與關(guān)系性數(shù)據(jù)庫完全不同的存儲方式,提供了靈活,大型,敏捷,可擴展的存儲模式,并且在有著復(fù)雜的數(shù)據(jù)情形下性能完全不遜色于RDBMS,而作為NOSQL中流行程度較高的數(shù)據(jù)庫,mongodb有著上手容易,數(shù)據(jù)查詢方式多樣等諸多特點,所以也深受...
摘要:是一個遺傳算法框架,這里是它的簡介。最小化問題使用負值的的最大化問題用正值。略種群種群橫線個體。這個種群是直接使用和函數(shù)來初始化的。個體之間分布在網(wǎng)格中每個格子包含一個個體。調(diào)用將會返回一個種群,個體是使用兩個索引可獲得的。 DEAP是一個python遺傳算法框架,這里是它的簡介。DEAP documentation今天整理一下DEAP的概覽,大體了解一下它的流程。初學(xué),不嚴謹,僅作為...
閱讀 2113·2021-11-16 11:45
閱讀 1185·2021-10-22 09:53
閱讀 4002·2021-09-07 10:26
閱讀 1209·2021-09-06 15:00
閱讀 2073·2019-08-28 18:09
閱讀 2795·2019-08-26 14:06
閱讀 3934·2019-08-26 13:48
閱讀 1296·2019-08-26 12:11