Mongoose 是 MongoDB 的 ODM(Object Document Mapper)。
- 什么是ODM? 其实和ORM(Object Relational Mapper)是同类型的工具。都是将数据库的数据转化为代码对象的库,使用转化后的对象可以直接对数据库的数据进行CRUD(增删改查)。
MongoDB
是文档型数据库(Document Database),不是关系型数据库(Relational Database)。而Mongoose
可以将 MongonDB 数据库存储的文档(documents)转化为 javascript 对象,然后可以直接进行数据的增删改查。
因为MongoDB
是文档型数据库,所以它没有关系型数据库joins
(数据库的两张表通过”外键”,建立连接关系。) 特性。也就是在建立数据的关联时会比较麻烦。为了解决这个问题,Mongoose
封装了一个Population
功能。使用Population
可以实现在一个 document 中填充其他 collection(s) 的 document(s)。
在定义Schema
的时候,如果设置某个 field 关联另一个Schema
,那么在获取 document 的时候就可以使用 Population 功能通过关联Schema
的 field 找到关联的另一个 document,并且用被关联 document 的内容替换掉原来关联字段(field)的内容。
接下来分享下:Query#populate
Model#populate
Document#populate
的用法
先建立三个Schema
和Model
:
1 | var mongoose = require('mongoose'); |
- 在上述的例子中,创建了三个 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。
创建一些数据到数据库:
1 | // 连接数据库 |
数据的准备就绪后,接下来就是探索populate
方法:
1. Query#populate
什么Query? Query(查询),可以快速和简单的从MongooDB查找出相应的 document(s)。 Mongoose 封装了很多查询的方法,使得对数据库的操作变得简单啦。这里分享一下populate
方法用法。
语法:
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
,可选,指定附加的其他查询选项,如排序以及条数限制等等。
1 | //填充所有 users 的 posts |
1 | Post.findOne({title: 'post-by-aikin'}) |
2. Model#populate
Model(模型),是根据定义的 Schema 编译成的抽象的构造函数。models 的实例 documents,可以在数据库中被保存和检索。数据库所有 document 的创建和检索,都通过 models 处理。
语法:
Model.populate(docs, options, [cb(err,doc)])
参数:
docs
类型:Document
或Array
。单个需要被填充的 doucment 或者 document 的数组。
options
类型:Object
。以键值对的形式表示。
keys:path
select
match
model
options
,这些键对应值的类型和功能,与上述Query#populate
方法的参数相同。
[cb(err,doc)]
类型:Function
,回调函数,接收两个参数,错误err
和填充完的doc(s)
。
1 | Post.find({title: 'post-by-aikin'}) |
3. Document#populate
Document,每个 document 都是其 Model 的一个实例,一对一的映射着 MongoDB 的 document。
语法:
Document.populate([path], [callback])
参数:
path
类型:String
或Object。与上述
Query#populate`方法的 path 参数相同。
callback
类型:Function
。回调函数,接收两个参数,错误err
和填充完的doc(s)
。
1 | User.findOne({name: 'aikin'}) |
博文涉及的完整例子在 gist 上。(ps: 貌似 gist 今天被墙了。)