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的官方文檔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章