在Express中對MongoDB資料庫進行增刪改查

  • 2020 年 2 月 23 日
  • 筆記

這兩天跟著B站的Johnny老師學習NodeJs+Express+MongoDB相關的知識點,前後跟著做了1小時搞定NodeJs(Express)的用戶註冊、登錄和授權Element UI + NodeJs(Express)全棧開發後台管理介面Express-9-MongoDB刪除產品和DELETE請求等系列影片。本篇部落格主要是學習在Express中如何對MongoDB資料庫進行增刪改查。

編碼前的準備工作

首先要安裝好NodeJs運行環境,配置好node和npm的環境變數,最好安裝淘寶 NPM 鏡像cnpm,安裝配置好npm後,打開終端運行npm install -g cnpm –registry=https://registry.npm.taobao.org命令全局安裝cnpm;然後在系統中安裝好MongoDB,關於如何在Windows系統下安裝MongoDB可以參考Windows 平台安裝 MongoDB-菜鳥教程。我使用的系統是Windows10系統,採用的開發工具是Visual Studio Code,另外還需要在VSCode中安裝REST Client插件,用於發送HTTP請求和查看服務端的響應資訊,類似於PostMan,不過Rest-Client插件可以直接在VSCode中發送HTTP的GET、POST、PUT、DELETE請求,對於開發人員來說很方便,具體可以參考Johnny老師的B站影片VSCode中類似PostMan的API介面請求利器 – rest client,這篇影片快速的講解了VSCode中Rest-Client的使用,具體的還可以看VSCode中Rest-Client的使用教程。 建立好上述開發環境後,打開VSCode,在一個目錄中新建一個EXPRESS-TEST的文件夾,用於存放項目文件,新建一個server.js文件用於存放程式碼,test.http存放rest-client編寫的介面用於測試客戶端的http請求。 然後在VSCode中打開終端,使用cnpm命令安裝express和MongoDB的資料庫模組mongoose和cors(支援跨域),命令如下:

cnpm install express  cnpm install mongoose  cnpm install cors

使用Express啟動http服務

Express 是一個保持最小規模的靈活的 Node.js Web 應用程式開發框架,為 Web 和移動應用程式提供一組強大的功能,簡單易用,下面的程式碼演示了如何使用Express在指定的4001埠上監聽,開啟一個http服務,當然埠可以隨意指定,只要和系統中其他不衝突即可,感覺使用起來比Java SpringBoot簡單不少。

const express = require('express')    const app = express()    // 在4001埠上監聽  app.listen(4001, () => {    console.log('App is listening on port 4001!')  })

在NodeJs中對MongoDB資料庫進行增刪改查

連接MongoDB資料庫

新建一個MongoDB資料庫模型,命名為express-test

const mongoose = require('mongoose')    mongoose.connect('mongodb://localhost:27017/express-test',    { useNewUrlParser: true,      useUnifiedTopology: true,      useCreateIndex: true,    })  // 創建產品Schema  const Productschema = new mongoose.Schema({      title: { type: String, unique: true}  })    // 定義MongoDB數據模型 (表=》集合)  const Product = mongoose.model('Product',Productschema)

新增產品

// 新增產品  app.post('/products', async function(req, res){    // 獲取客戶端請求的json數據    const data = req.body;    // 插入數據到產品表集合中    const product = await Product.create(data)    res.send(product)  })

查詢所有產品記錄

// 查詢所有產品記錄  app.get('/products', async function(req, res){    // const data = await Product.find().skip(1).limit(2)    // const data = await Product.find().where({    //   title: '華為'    // })    const data = await Product.find().sort({ _id: -1 })    res.send(data)  })

根據title產品名稱查詢指定的產品資訊

// 根據title名稱查詢指定的產品資訊  app.get('/products/:titleName', async function(req,res){    const titleName = req.params.titleName;    Product.find({ "title": titleName }, function(err, doc){      if(err) {        console.log(err)      } else {        res.json(doc)        // res.send(res.json(doc))      }    })  })

使用PUT請求修改產品資訊

// 修改產品和PUT請求  // patch表示部分修改,put表示覆蓋  //app.patch();  app.put('/products/:id', async function(req,res){    const product = await Product.findById(req.params.id);    // 將客戶端傳過來的title賦值給產品(賦值不需要非同步,因為它只是javascript中的一個記憶體操作,而查詢、保存數據都需要和MongoDB連接需要非同步)    product.title = req.body.title;    // 保存產品    await product.save();    res.send(product);  })

根據客戶端傳遞的id號刪除某個產品

app.delete('/products/:id', async function(req, res){    // 根據客戶端傳遞過來的id從MongoDB資料庫中查詢對應的產品    const product = await Product.findById(req.params.id);    // 刪除查詢到的產品    await product.remove();    // 向客戶端發送刪除成功的資訊    res.send({      success: true,    })  })

使用Rest-Client編寫http請求

VScode中的Rest-Client有一個規定,就是http請求文件必須以http為後綴,比如說tets.http文件。 本EXPREES-TEST項目中對應的test.http測試文件如下:

@url=http://localhost:4001  @json=Content-Type: application/json    ### products page  GET {{url}}/products    ### post 新增產品  POST {{url}}/products  Content-Type: application/json    {    "title": "我的手機"  }    ### put 修改產品  PUT {{url}}/products/5e48c999e12a60686cbad30b  Content-Type: application/json    {    "title": "Apple"  }    ### 刪除某個產品  DELETE {{url}}/products/5e4aaa812d6048635c877fd1    ### 靜態文件託管  get {{url}}/index.html

完整的示例程式碼

/* jshint esversion: 8 */  // expess模組  const express = require('express')    const app = express()    app.use(express.json())    // MongoDB模組  const mongoose = require('mongoose')    mongoose.connect('mongodb://localhost:27017/express-test',    { useNewUrlParser: true,      useUnifiedTopology: true,      useCreateIndex: true,    })    // 創建產品Schema  const Productschema = new mongoose.Schema({      title: { type: String, unique: true}  })    // 定義MongoDB數據模型 (表=》集合)  const Product = mongoose.model('Product',Productschema)    // 往MongoDB資料庫中插入數據  // Product.insertMany([  //   {title: 'Apple'},  //   {title: '華為'},  //   {title: '三星'},  //   {title: '小米'},  //   {title: 'Oppo'},  //   {title: 'Vivo'},  // ])    // 刪除所有數據  // Product.deleteMany({}, function(err, doc) {  //   if(err) {  //     console.log(err)  //   } else {  //     console.log(doc)  //   }  // });    // 允許跨域  app.use(require('cors')())    // 路由:express 靜態文件託管  // app.use('/static', express.static('public'))  app.use('/', express.static('public'))      // 新增產品  app.post('/products', async function(req, res){    // 獲取客戶端請求的json數據    const data = req.body;    // 插入數據到產品表集合中    const product = await Product.create(data)    res.send(product)  })    // 查詢所有產品記錄  app.get('/products', async function(req, res){    // const data = await Product.find().skip(1).limit(2)    // const data = await Product.find().where({    //   title: '華為'    // })    const data = await Product.find().sort({ _id: -1 })    res.send(data)  })    // 查詢單個產品記錄 產品詳情頁的介面  // app.get('/products/:id', async (req,res) => {  //   const data = await Product.findById(req.params.id)  //   res.send(data)  // })    // 根據title名稱查詢指定的產品資訊  app.get('/products/:titleName', async function(req,res){    const titleName = req.params.titleName;    Product.find({ "title": titleName }, function(err, doc){      if(err) {        console.log(err)      } else {        res.json(doc)        // res.send(res.json(doc))      }    })  })    // 修改產品和PUT請求  // patch表示部分修改,put表示覆蓋  //app.patch();  app.put('/products/:id', async function(req,res){    const product = await Product.findById(req.params.id);    // 將客戶端傳過來的title賦值給產品(賦值不需要非同步,因為它只是javascript中的一個記憶體操作,而查詢、保存數據都需要和MongoDB連接需要非同步)    product.title = req.body.title;    // 保存產品    await product.save();    res.send(product);  })    // 修改產品資訊  app.get('/products/update/:titleName', async function(req,res){    const titleName = req.params.titleName;    Product.update({ title : titleName }, {"$set":{title: "My Oppo A5"}}, function(err, doc){      if(err) {        console.log(err)      } else {        res.json(doc)        // res.send(res.json(doc))      }    })  })    // 根據客戶端傳遞的id號刪除某個產品  app.delete('/products/:id', async function(req, res){    // 根據客戶端傳遞過來的id從MongoDB資料庫中查詢對應的產品    const product = await Product.findById(req.params.id);    // 刪除查詢到的產品    await product.remove();    // 向客戶端發送刪除成功的資訊    res.send({      success: true,    })  })    // 在4001埠上監聽  app.listen(4001, () => {    console.log('App is listening on port 4001!')  })

我在實際使用VSCode的過程中,當使用async集合await調用MongoDB實現非同步調用時保存,需要在源程式碼文件server.js的頂部添加如下一行:

/* jshint esversion: 8 */ 

這樣就可以正常使用async集合await調用非同步介面了。