mongoose --- populate主要操作以及简单和$lookup对比

简单的创建声明三张表:user/department/project

const UserSchema = new mongoose.Schema({
  username: { type: String, required: true },
  password: { type: String, required: true },
  department: { type: mongoose.Schema.Types.ObjectId, ref: 'Department'}
  project: { type: mongoose.Schema.Types.ObjectId, ref: 'Project'}
})

const DepartmentSchema = new mongoose.Schema({
  name: { type: String, required: true },
  project: { type: mongoose.Schema.Types.ObjectId, ref: 'Project'}
})

const ProjectSchema = new mongoose.Schema({
  name: { type: String, required: true },
  owner: { type: mongoose.Schema.Types.ObjectId, ref: 'User'}
})

请忽略开发语言0_0…

  1. 查询user表,以及关联查询project和department。深度为1的多个关联查询用数组,单个用字符串即可。
    model.User.find().populate(['department','project'])
  2. 查询user表,关联查询project并且再查询owner字段,即深度为2的关联查询。
    model.User.find().populate({ path: 'project', populate: { path: 'owner' } })
  3. 在2的基础上查询owner的时候只想要name字段,而password不返回。
    model.User.find().populate({ path: 'project', populate: { path: 'owner', select: 'name' } })
  4. 1和2结合一起,即需要关联查询project和department,且project中再关联查询owner字段
const pop = [
  {
    path: 'department'
  },
  {
    path: 'project',
    populate: { path: 'owner' }
  },
];
model.User.find().populate(pop);

另外有几点需要注意:

  • 如果关联的字段是数组的话,跟上面用法是一样的。
  • 如果关联字段查询不到的话,比如上面user.project = null,如果是数组字段则为空数组。
  • 关联的字段类型可以是ObjectId, Number, String, and Buffer,但是官方文档上说:However, you should use ObjectId unless you are an advanced user and have a good reason for doing so.

下面说一下跟$lookup的关系

  1. user表中查到department可以用populate,也可以用$lookup。但如果想在department表中查到user则只能用$lookup。也就是说正向关联的话两者都能用,反向的话只能用$lookup(但个人觉得正向的话还都是用populate,因为$lookup写法较麻烦)。
  2. populate用的是refs查询,在性能上$lookup比较有优势,比如查询user表一次出来10条记录,再用refs查询project需要10次,而$lookup只需要1次。当然查询次数固然会影响整个查询过程消耗的时间,但相比在网络中传输数据所耗费的时间还是可以接受的。
  3. 简单给出$lookup的用法。
    在department中查询到该部门下所有的user在department中查询到该部门下所有的user在department中查询到该部门下所有的user在department中查询到该部门下所有的user
model.Department.aggregate([ 
  {
    $lookup: {
      from: 'users',  // 从哪个Schema中查询(一般需要复数,除非声明Schema的时候专门有处理)
      localField: '_id',  // 本地关联的字段
      foreignField: 'department', // user中用的关联字段
      as: 'users' // 查询到所有user后放入的字段名,这个是自定义的,是个数组类型。
    }
  }
]);

更加详细的内容参考populate的官方文档

你可能感兴趣的:(mongoose)