---
# System prepended metadata

title: "\U0001F3C5 Day 39"
tags: [Node.js 直播班 - 2022 春季班]

---

---
tags: Node.js 直播班 - 2022 春季班
---
# 🏅 Day 39



## 追蹤 / 取消追蹤使用者功能

**執行流程：**
A 使用者對其他使用者（如 B) 點擊追蹤時，會分別在 A 使用者的 user 資料 followings 欄位加入 B 的 ID，B 使用者的 user 資料 followers 欄位也會加入 A 的 ID
若執行取消追蹤則從 A 使用者的 user 資料 followings 欄位、B 使用者的 user 資料 followers 欄位移除 ID

**實作前準備**
需先於 user Model 中加入 followers 與 follwing 欄位，預計會加入使用者 ID 及加入時間（[參考](https://github.com/gonsakon/express-week4-sample/blob/week8/models/usersModel.js#L29-L46)）
`由於社群網站在設計上會限制 500 位會員數，預計在兩個欄位中分別加入 499 個 user ID 不會超過 MongoDB Document 的 16mb 容量限制，因此可使用直接將 ID 加入 user 資料的方式執行`
```javascript
followers: [
  {
    user: { type: mongoose.Schema.ObjectId, ref: 'User' },
    createdAt: {
      type: Date,
      default: Date.now
    }
  }
  ],
  following: [
    {
      user: { type: mongoose.Schema.ObjectId, ref: 'User' },
      createdAt: {
        type: Date,
        default: Date.now
      }
    }
  ]
```






### 題目（將答案寫在 HackMD 並提交至回報區）
**實作使用者追蹤、取消追蹤功能**
可參考第八週[範例程式碼](https://github.com/gonsakon/express-week4-sample)
- 設計追蹤路由 POST`users/:id/follow`、取消追蹤路由 DELETE `users/:id/unfollow`
- 需登入通過 JWT 驗證才能請求
- 不能追蹤或取消追蹤帳號本人
- 追蹤與取消追蹤都需調整追蹤者與被追蹤者雙方的 user 資料
    - 使用 updateOne() 搭配 `$addToSet` `$pull` 將使用者 ID 加入或移除
- 準備好兩個已註冊過的帳號，測試可以正確互相追蹤以及取消追蹤

回報流程
---
請同學依照下圖教學觀看解答、回報答案:

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

回報格式：請在「回報區」貼上 CodePen 或 HackMD 連結回報答案 (為了統計人數，請同學依序加上「報數」)


<!-- 解答
models/usersModel.js
https://github.com/gonsakon/express-week4-sample/blob/week8/models/usersModel.js#L29-L46

routes/users.js
參考 https://github.com/gonsakon/express-week4-sample/blob/week8/routes/users.js#L90-L144
```javascript
router.post('/:id/follow',isAuth, handleErrorAsync(async(req, res, next) =>{

  if (req.params.id === req.user.id) {
    return next(appError(401,'您無法追蹤自己',next));
  }
  await User.updateOne(
    {
      _id: req.user.id,
      'following.user': { $ne: req.params.id }
    },
    {
      $addToSet: { following: { user: req.params.id } }
    }
  );
  await User.updateOne(
    {
      _id: req.params.id,
      'followers.user': { $ne: req.user.id }
    },
    {
      $addToSet: { followers: { user: req.user.id } }
    }
  );
  res.status(200).json({
    status: 'success',
    message: '您已成功追蹤！'
  });
}))

router.delete('/:id/unfollow',isAuth, handleErrorAsync(async(req, res, next) =>{

  if (req.params.id === req.user.id) {
    return next(appError(401,'您無法取消追蹤自己',next));
  }
  await User.updateOne(
    {
      _id: req.user.id
    },
    {
      $pull: { following: { user: req.params.id } }
    }
  );
  await User.updateOne(
    {
      _id: req.params.id
    },
    {
      $pull: { followers: { user: req.user.id } }
    }
  );
  res.status(200).json({
    status: 'success',
    message: '您已成功取消追蹤！'
  });
}))
```

-->

回報區
---

| 報數 | 組別 / 名字 | codepen / hackMD / 其他回饋 |
| ---- | ----------- | ------------------ |
|1|  第 3 組 / Hobby  | [HackMD](https://hackmd.io/@hobbyling/day39)   |
|2|  第 5 組 @ Hazel  | [HackMD@Hazel](https://hackmd.io/@hazelwu/day39)   |
|3|  第 4 組 / 苡安  | [HackMD](https://hackmd.io/f-tmyR1ZQvqsni1glhyz8A)   |
|3|  第 14 組｜East  | [HackMD](https://hackmd.io/TQGzSJ0cSMaTOBDxd9GPIw)   |
|4|  第 11 組｜Han Lai  | [HackMD](https://hackmd.io/3v8lZ4oZSUGqLS4Gm6QVOA?view)   |
|5|  第 16 組｜皓皓  | [HackMD](https://hackmd.io/@cutecat8110/rJdddlVs5)   |
