Mongoose 使用之 Population

何为 Population

用过 MongoDB 的人应该都知道它是没有关系型数据库里的 join 特性的,这意味着当咱们使用 MongoDB 读取某个 document 及其关联的 document 的字段的时候,变得尤其麻烦。数据库

基于此,Mongoose 封装了一个 population 的功能,当你在定义 Schema 的时候指定了某个 field 是引用了另外一个 Schema ,那么你在获取 document 的时候就可使用 populate 方法让 Mongoose 帮你经过引用 Schema 和 id 找到关联的另外一个 document,而且用该 document 的内容替换掉原来引用字段的内容,使引用的 ducoment 使用起来就像是内嵌的 document 同样方便。数组

定义带有引用字段的 Schema

首先,若是要使用这个功能,必须给你的“外键字段”定义 Mongoose 的“外键约束”(这里借用关系型数据库的术语,只是为了帮助理解)。假设咱们有一个用户的 Schema ,其中有一个字段是followings,保存用户关注了的其余用户,相似微博。Mongoose 的 Schema 定义以下:mongoose

var mongoose = require('mongoose')
  , Schema = mongoose.Schema
  
var UserSchema = Schema({
  name    : String,
  followings : [{ type: Schema.Types.ObjectId, ref: 'User' }]
});
    
var User = mongoose.model('User', UserSchema);

保存引用字段

而后咱们建立两个 User 实例,而且先将其中之一保存进数据库(为了产生 _id ):函数

var lily = new User({name: 'lily'})
   ,lucy = new User({name: 'lucy'});
lily.save(cb);

lily 保存成功后,咱们再在回调函数 cb 中保存 lucy ,不过这个时候假设 lucy 关注了 lily:ui

function cb(err) {
    if(err) throw err;
    lucy.followings.push(lily._id);// line 1
    lucy.save(cb1);
}

这样就保存完成了。不过好像咱们没用引用字段以前也是这么保存的吧?有没有更直接一点的?有,你其实能够将 line 1 的语句改为如下形式, Mongoose 也会自动帮你作内部解析的:code

lucy.followings.push(lily);

这样看起来代码就更接近天然语言了,有点ORM的味道。对象

查询 document

固然,上面的例子可能对开发者来讲没有什么太大的用处,那么就来看看 population 在获取 document 的时候能给咱们带来什么好处吧。排序

假设咱们如今要找到 lucy 的信息以及她所关注的用户,咱们能够这样:开发

User.findOne({name: 'lucy'}).exec(cb2);

可是这样拿出来的 lucy 的 followings 是一组存储了 ObjectId 的数组,还得去一个个查找对应的用户,多麻烦啊。因此这个时候用 population 就简单多了,直接指定你想要 populate 哪一个引用字段:get

User.findOne({name: 'lucy'}).populate('followings').exec(cb2);

这样的话,在回调函数 cb2 中你获得的就是一个存储了若干个 User 对象的数组了。

populate 方法

populate 方法能够用在 document 上、 model 上或者是 query 对象上,这意味着你几乎能够在任何地方调用这个方法以填充你的引用字段。

固然,populate 方法在不一样对象上参数不大同样,可是都接收一个option的参数,你能够用这些参数指定:

  • path: 以空格分隔的引用字段的名称
  • select: 填充引用 document 中的哪些字段
  • match: 可选,指定附加的查询条件
  • model: 可选,指定引用的 model
  • options: 可选,指定附加的其余查询选项,如排序以及条数限制等等

引用字段的类型

目前,Mongoose 只支持如下几种引用字段的类型:

  • ObjectId
  • Number
  • String
  • Buffer

并且天然而然,引用 document 的主键类型必须和引用字段类型相对应。在生产环境中,推荐主键类型和引用类型都使用 ObjectId ,一是由于 ObjectId 不包含业务含义,二是 ObjectId 不大可能重复,三是由于 Mongoose 默认生成的主键类型就是 ObjectId ,能够减小不少配置的操做。

更多信息请关注这里

相关文章
相关标签/搜索