---
# System prepended metadata

title: 第二週 － Node.js NPM 整合 MongoDB
tags: [Node.js 企業專題班 - 2024 春季班, Node.js 入門班 - 2024 春季班]

---



# 第二週 － Node.js NPM 整合 MongoDB
1. 錄影
2. 提醒關於之後的錄影檔都會如何存放
3. [Adobe XD 設計稿](https://xd.adobe.com/view/c0763dbe-fc15-42e8-be0b-8956ed03e675-9525/grid)
4. [講義簡報](https://whimsical.com/mongoose-YKTKL5aF4pHQbkemgQTMZH)
5. 六角後端鬼故事傳奇

## 講解大綱
* Mongoose 講解
* Schema 設計
* 何謂 Model？
* 第二週主線任務設計
## 公布最終作業使用者故事

1. 此為 NFT 會員制的動態牆，僅有限量 VIP 可以加入討論
2. 在 NFT 合約上，有限制永久只有 500 位會員參與此平台

## NPM
* dotenv：環境變數
* [Mongoose](https://mongoosejs.com/)




## 常見 Mongoose 指令
### 連線語法
若 localhost 不行，可改為 `mongodb://127.0.0.1:27017/testPost`
```=javascript
const http = require('http');
const mongoose = require('mongoose');
mongoose
.connect("mongodb://localhost:27017/testPost")
.then(() => console.log('資料庫連接成功'));
// schema 開始 

// schema 結束
const requestListener = async(req, res)=>{
    res.end();
}
const server = http.createServer(requestListener);
server.listen(3000);
```
> mongodb://localhost:27017/posts

### 建立 Schema
```=javascript
const postSchema = new mongoose.Schema(
    {
      content: {
        type: String,
        required: [true, 'Content 未填寫']
      },
      image: {
        type:String,
        default:""
      },
      createdAt: {
        type: Date,
        default: Date.now(),
        select: false
      },
      name: {
          type: String,
          required: [true, '貼文姓名未填寫']
      },
      likes: {
          type:Number,
          default:0
        }
    }
);
const Post = mongoose.model('Post', postSchema);
const init = async()=>{
        const AllPost =  await Post.find();
        console.log(AllPost)
    }
init();
```

### CURD 語法
* 新增：[Model.create()](https://mongoosejs.com/docs/api/model.html#model_Model.create)
* 刪除：[Model.findByIdAndDelete()](https://mongoosejs.com/docs/api/model.html#model_Model.findByIdAndDelete)
* 更新：[Model.findByIdAndUpdate()](https://mongoosejs.com/docs/api/model.html#model_Model.findByIdAndUpdate)
* 查詢：[Model.find()](https://mongoosejs.com/docs/api/model.html#model_Model.find)

```
await Post.findByIdAndUpdate(id,editContent) // 更新單筆
await Post.deleteMany({}); //刪除全部
await Post.findByIdAndDelete(id); // 刪除單筆
```
:::spoiler 完整 Code
## code

```=JavaScript
const http = require('http');
const mongoose = require('mongoose');
mongoose
.connect("mongodb://localhost:27017/testPost")
.then(() => console.log('資料庫連接成功'));

const postSchema = new mongoose.Schema(
    {
      content: {
        type: String,
        required: [true, 'Content 未填寫']
      },
      image: {
        type:String,
        default:""
      },
      createdAt: {
        type: Date,
        default: Date.now(),
        select: false
      },
      name: {
          type: String,
          required: [true, '貼文姓名未填寫']
      },
      likes: {
          type:Number,
          default:0
        }
    }
);
const Post = mongoose.model('post', postSchema);

const requestListener = async(req, res)=>{
    const headers = {
        'Access-Control-Allow-Headers': 'Content-Type, Authorization, Content-Length, X-Requested-With',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'PATCH, POST, GET,OPTIONS,DELETE',
        'Content-Type': 'application/json'
    }
    let body = "";
    req.on('data', chunk=>{
        body+=chunk;
    })
    
    if(req.url=="/posts" && req.method == "GET"){
        const post = await Post.find();
        res.writeHead(200,headers);
        res.write(JSON.stringify({
            "status": "success",
            post
        }));
        res.end();
    }else if(req.url=="/posts" && req.method == "POST"){
        req.on('end',async()=>{
            try{
                const data = JSON.parse(body);
                if(data.content !== undefined){
                    const newPost = await Post.create(
                        {
                            name: data.name,
                            content: data.content,
                        }
                    );
                    res.writeHead(200,headers);
                    res.write(JSON.stringify({
                        "status": "success",
                        "data": newPost,
                    }));
                    res.end();
                    
                }else{
                    res.writeHead(400,headers);
                    res.write(JSON.stringify({
                        "status": "false",
                        "message": "欄位未填寫正確，或無此 todo ID",
                    }));
                    res.end();
                }
            }catch(error){
                res.writeHead(400,headers);
                res.write(JSON.stringify({
                    "status": "false",
                    "message": error,
                }));
                res.end();
            }
        })
    }else if(req.url.startsWith("/posts/") && req.method=="DELETE"){
        const id = req.url.split('/').pop();
        await Post.findByIdAndDelete(id);
        res.writeHead(200,headers);
        res.write(JSON.stringify({
            "status": "success",
            "data": null,
        }));
        res.end();
    }else if(req.method == "OPTIONS"){
        res.writeHead(200,headers);
        res.end();
    }else{
        res.writeHead(404,headers);
        res.write(JSON.stringify({
            "status": "false",
            "message": "無此網站路由"
        }));
        res.end();
    }
}
const server = http.createServer(requestListener);
server.listen(3000);
```
:::




## 本堂作業

* 講解主線任務
