# 🏅 Day 18 - Mongoose - Populate Mongoose 有提供 `populate()` 方法並搭配在 schema 設定 ref 關聯,就可以將其他 collection 的資料關聯到目前在操作的 collection 以作業設計稿貼文為例,貼文除了貼文內容、圖片、貼文建立時間,也會需要使用者的資料來記錄該則貼文是哪位使用者發布的 舉例: ```javascript= const mongoose = require('mongoose'); // 使用者 Schema、Model const userSchema = new mongoose.Schema({ name: { type: String, required: [true, '名字未填寫'] }, email: { type: String, required: [true, 'Email 未填寫'], select: false }, photo: { type: String, default: '' } }, { versionKey: false }); const User = mongoose.model('User', userSchema); // 貼文 Schema、Model const postSchema = new mongoose.Schema({ user: { type: mongoose.Schema.ObjectId, // users collection 的 _id ref: 'User' // 使用者的 Model 名稱 }, content: { type: String, required: [true, '貼文內容未填寫'] }, image: { type: String, default: '' }, createdAt: { type: Date, default: Date.now }, likes: { type: Number, default: '' } }, { versionKey: false }); const Post = mongoose.model('Post', postSchema); ``` > Post 要關聯到 User 需在 schema 的 `user` 欄位設定 `ref` 告訴 Mongoose 關聯資料時要使用哪個 Model 接下來就可以使用 `populate()` 加入相關設定,就可以在取得 Post 資料時依據 Schema 的設定取得 User 的 collection 資料 大致如下: ```javascript= Post.find() .populate({ path: 'user', select: 'name' }) ``` 取得 Post 資料時: - `path` 設定為有關聯到 User 的屬性 `user`,就會關聯到 User 的 collection 並找出符合該 id 的資料 - `select` 可以指定要取出該資料的哪個欄位,以上方範例來說就會取出 `name` 欄位。 使用空格間隔可以取出多個欄位,像是:`select: 'name photo'`,就會取出 `name` 和 `photo` 欄位 ### 參考資源 - [Mongoose: Query Population](https://mongoosejs.com/docs/populate.html) - [Mongoose: Schema ref](https://mongoosejs.com/docs/api/schematype.html#SchemaType.prototype.ref()) 題目 --- 延續上方範例,貼文下方的按讚 `likes` 通常會需要知道是哪位使用者按讚的,請嘗試調整貼文的 Schema,讓 `likes` 關聯使用者,當取出貼文資料時可以關聯使用者,並取出使用者的名字與圖片資料 完整下方程式碼(補上 `...` 的部分) ```javascript= const mongoose = require('mongoose'); // 使用者 Schema、Model const userSchema = new mongoose.Schema({ name: { type: String, required: [true, '名字未填寫'] }, email: { type: String, required: [true, 'Email 未填寫'], select: false }, photo: { type: String, default: '' } }, { versionKey: false }); const User = mongoose.model('User', userSchema); // 貼文 Schema、Model const postSchema = new mongoose.Schema({ user: { type: mongoose.Schema.ObjectId, ref: 'User' }, content: { type: String, required: [true, '貼文內容未填寫'] }, image: { type: String, default: '' }, createdAt: { type: Date, default: Date.now }, likes: ..., }, { versionKey: false }); const Post = mongoose.model('Post', postSchema); // 取得貼文資料 Post.find() .... ``` ## 回報流程 將答案寫在 CodePen 並複製 CodePen 連結貼至底下回報就算完成了喔! 解答位置請參考下圖(需打開程式碼的部分觀看) ![](https://i.imgur.com/vftL5i0.png) <!-- 解答: ```javascript= const mongoose = require('mongoose'); // 使用者 Schema、Model const userSchema = new mongoose.Schema({ name: { type: String, required: [true, '名字未填寫'] }, email: { type: String, required: [true, 'Email 未填寫'], select: false }, photo: { type: String, default: '' } }, { versionKey: false }); const User = mongoose.model('User', userSchema); // 貼文 Schema、Model const postSchema = new mongoose.Schema({ user: { type: mongoose.Schema.ObjectId, ref: 'User' }, content: { type: String, required: [true, '貼文內容未填寫'] }, image: { type: String, default: '' }, createdAt: { type: Date, default: Date.now }, likes: [{ type: mongoose.Schema.ObjectId, ref: 'User' }], // 一則貼文會有很多個讚,所以使用陣列 }, { versionKey: false }); const Post = mongoose.model('Post', postSchema); // 取得貼文資料 Post.find() .populate({ path: 'user', select: 'name photo' }) ``` --> 回報區 --- <!-- 將答案貼至下方表格內,格式: | Discord 暱稱 | [CodePen](連結) | --> | Discord | CodePen / 答案 | |:-------------:|:-----------------:| | xxx | [CodePen]() | | Aida | [CodePen]( https://codepen.io/ada23410/pen/NWmmgJq?editors=0010 ) | | 苡安 | [hackmd](https://hackmd.io/@L7K9-66lSeagS28AP0_GjQ/By7GKd2WR) | | Chia Pin | [CodePen]( https://codepen.io/joker-cat/pen/YzMMraZ ) | | Ciel | [CodePen](https://codepen.io/nycteachen/pen/qBwwpvz) | | wei | [CodePen](https://codepen.io/Wei-the-sasster/pen/XWQQZGb?editors=0010) | | tung030374 | [CodePen](https://codepen.io/tung__u/pen/NWmmBrJ?editors=0010) | | jenny7532 | [CodePen](https://codepen.io/wei-chen-wu/pen/poBmzrO) | | william威良 | [CodePen](https://codepen.io/snowman12320/pen/PogvOze?editors=1010) | | william_hsu | [CodePen](https://codepen.io/william8815/pen/poBmapZ) | | Lobinda| [HackMD](https://hackmd.io/JfwTI4LfTAW4siPJ_JtNbQ) | | 2魚 | [CodePen](https://codepen.io/ijrekmsn-the-sans/pen/XWQLbQL) | | Mei|[CodePen](https://codepen.io/l_umei/pen/XWQLKpJ)| |Benson|[CodePen](https://codepen.io/nosneb83/pen/BaEgRem)| | albertyang3576 | [CodePen](https://codepen.io/albertyang3576/pen/dyLBrVN)| | ej_chuang | [CodePen](https://codepen.io/EJChuang/pen/LYvKwpz)| | runweiting | [CodePen](https://codepen.io/weiting14/pen/LYvwxMx)| | Tiya | [CodePen](https://codepen.io/Tiya_blank/pen/rNbQPbY)| | Fabio20 | [CodePen](https://codepen.io/fabio7621/pen/ExzYrxX) | | Hank | [CodePen](https://codepen.io/tw1720/pen/oNOOQgW) |