# 🏅 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) |