---
# System prepended metadata

title: "\U0001F3C5 Day 17 - Mongoose - Populate"
tags: [Node.js 直播班 - 2023 春季班]

---

---
tags: Node.js 直播班 - 2023 春季班
---

# 🏅 Day 17 - Mongoose - Populate

Mongoose 有提供 `populate()` 方法，可以將其他 collection 的資料關聯到目前在操作的 collection

這裡引用官方文件中的範例
```javascript
const mongoose = require('mongoose');
const { Schema } = mongoose;

const personSchema = Schema({
  _id: Schema.Types.ObjectId,
  name: String,
  age: Number,
  stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});

const storySchema = Schema({
  author: { type: Schema.Types.ObjectId, ref: 'Person' },
  title: String,
  fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});

const Story = mongoose.model('Story', storySchema);
const Person = mongoose.model('Person', personSchema);
```
可以看到上方最後兩行有兩個 Model，分別是 Story 和 Person，兩者也都有連到各自的資料庫 collection
personSchema 中的 `stories` 欄位關聯至 storySchema 的 `id` 欄位，storySchema 的 `author` 及 `fans` 欄位，其中 `ref` 選項是告訴 Mongoose 關聯資料時要使用哪個 Model

接下來取得資料時就可以使用 `populate()` 加入相關設定，就可以在取得資料時依據 Schema 的設定取得其他 collection 的資料
```javascript
Story.
  find().
  populate({ path: 'fans', select: 'name' })
```
取得 Story 資料時，資料的 fans 欄位就會關聯至 Person collection，找出符合該 id 的 document，`select` 是指定要取出該 document 的哪些欄位，上方範例是取出 document 中的 `name` 欄位
取出多個欄位的寫法為 `select: 'name age'`，就會取出 document 中的 `name` 和 `age` 欄位


### 參考資源

- [Mongoose v6.3.1: Query Population](https://mongoosejs.com/docs/populate.html)

## 題目（將答案寫在 HackMD 並提交至回報區）
以下為書籍與作者的 collection，請填入對應答案，讓取出單筆書籍資料時，可以關聯至 author 的資料

```javascript
const mongoose = require('mongoose');

const authorSchema = new mongoose.Schema({
    name: String,
    introduction: String
  }, { versionKey: false }
);

const bookSchema = new mongoose.Schema({
  author : { type: mongoose.Schema.ObjectId, ref: /*請填入答案*/ },
  title: String
}, { versionKey: false }
);

const Author = mongoose.model('Author', authorSchema);
const Book = mongoose.model('Book', bookSchema);
```
取出所有 books 的資料，關聯 author 欄位並指定顯示 author 資料的 name 欄位
```javascript
Book.find({_id: id })/*請填入答案*/
```
可使用此[專案](https://github.com/dogwantfly/mongoose-populate)練習及測試是否可正確運作，流程為以下
- 新增一筆 author 資料
- 帶入 author id 新增一筆 book 資料
- 以 book id 取得指定的 book 資料，並有正確顯示出 author 的 name
取得單筆 book 資料範例
```json
{
  "status": "success",
  "data": {
    "book": [
      {
        "_id": "62700cf6fe019820d43e5332",
        "author": {
          "_id": "62700a66e6922ea65f83054b",
          "name": "Mike"
        },
        "title": "book title"
      }
    ]
  }
}
```



## 回報流程

將答案連結貼至底下回報就算完成了喔! 
解答位置請參考下圖（需打開程式碼的部分觀看）

![](https://i.imgur.com/vftL5i0.png)

<!-- 解答：  

```javascript
// models/books.js
const bookSchema = new mongoose.Schema({
  author : { type: mongoose.Schema.ObjectId, ref: 'Author' },
  title: String
}, { versionKey: false }
);

// models/books.js
 const book = await Book.find({_id: id }).populate({
      path: 'author',
      select: 'name'
    });

```

-->



回報區
---

| 報數 |       組別／Discord 名字       |                            Codepen／HackMD／其他回饋                            |
|:----:|:-----------------------:|:-------------------------------------------------------------------------:|
| 1 | 北 10 組 / Benson | [Github Benson - Day 17](https://github.com/ioveasdkre/HexschoolOperation/tree/main/NodejsEnterpriseClass/day40-tasks/day17/app.ts) |
| 2 | 中 4 組 / jimkk159 | [HackMD - Day 17](https://hackmd.io/NEo6-G82Ty-44lLyWv6JnQ) |
|  3  |  北 12 組 / Sam Lin  | [GitHub - Day 17](https://github.com/samlin1122/hex-school/blob/main/daily-challenges/day17.js) |
| 4 | 北 1 組 / PittWu | [Blog Post - Day 17](https://pitt-wu-blog.vercel.app/docs/day17-mongoose-populate) |
|  5 | 北 13 組 / Louisa  | [GitHub - Day 17](https://github.com/louisa0416/NodejsEnterpriseClass/tree/master/daily-task/day17) |
|  6 | 南 1 組 / hiYifang  | [HackMD - Day 17](https://hackmd.io/@gPeowpvtQX2Om6AmD-s3xw/ryrhdUASq) |

