在MongoDB中没有关系型数据库的join特性,所以在document进行相互关联的时候就比较麻烦。
在mongoose中有一个population
用于解决这类问题。在定义Schema
的时候,如果设置某个field
关联另一个Schema
,那么在获取document
的时候就可以使用Population
功能通过关联Schema
的field
找到关联的另一个document
,并且用被关联document
的内容替换掉原来关联field
的内容。
例子
下面我拿官方的例子来说明
1 | var mongoose = require('mongoose'); |
首先先定义两个model,并且这两个model的schema相互引用。可以看到在person的stories字段(field )中我们定义了数组,表示关联的数据解析为数组。其中ref选项告诉mongoose在使用populate的时候使用什么model,并且后续所有的传入的_id都要在这个model之中。
保存数据
1 | var author = new Person({ |
保存数据的时候并没有什么不同,只是记得要分配下_id,若是_ids,则把所有需要展现的document的_id做成一个数组传入。
解析出引用
上面做的一些操作并没有什么特别的,但接下来我们可以看到通过populate我们解析除了内嵌的关联document。
1 | Story. |
下面我说下populate方法的常用用法
Query#populate
就是查询语句之后可以调用populate
语法1
**`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 |
Model#populate
model直接调用populate
语法
1 | **`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'}) |
Document#populate
document直接调用populate
语法
1 | **`Document.populate([path], [callback])`** |
参数
- path
类型:String或Object。与上述Query#populate`方法的 path 参数相同。
- callback
类型:Function。回调函数,接收两个参数,错误err和填充完的doc(s)。
例子
1 | User.findOne({name: 'aikin'}) |
跨越等级的Populate
populate可以进行多重引用
1 | var userSchema = new Schema({ |