Mongoose在Express、Koa、 Egg中使用對比

慄路遙發表於2022-11-23

Mongoose是什麼?

簡單一句話概括:Mongoose是一套操作MongoDB資料庫的介面。

開始

在使用mongoose之前,需要事先安裝好Node環境MongoDB資料庫
以上準備就緒我們就可以了。

在Express Koa Egg中的使用

  • 在Express中
    首先初始化專案

    npm init //初始化專案
    npm i xxx --save//安裝各種依賴例如express nodemon ...

    目錄如下

    |-express
    |  | -- db//啟動mongodb資料庫的dbpath路徑
    |  | --model//資料庫中表的模型
    |  | --node_modules
    |  | --public//公共資源
    |  | --route//路由
    |  | --schema//模式型別
    |  | --app.js//入口檔案
    |  | --package.json//配置檔案

    安裝mongoose。

    npm install mongoose//安裝mongoose

    在package.json

    {
    "dependencies": {
      "body-parser": "^1.19.0",
      "connect-multiparty": "^2.2.0",
      "express": "^4.17.1",
      "formidable": "^1.2.2",
      "http-proxy-middleware": "^2.0.0",
      "mongoose": "^5.12.13",
      "multer": "^1.4.2",
      "multiparty": "^4.2.2",
      "nodemon": "^2.0.7",
      "xlsx": "^0.17.4"
    }
    }
    

    在app.js中引入依賴

    const express=require("express");//引入express
    const mongoose = require('mongoose');//引入mongoose
    const app=express();
    const port=8080;//埠號
    mongoose.connect('mongodb://localhost:27017/Management',{useNewUrlParser:true,useUnifiedTopology:true},function(err){
      if(err){
          console.log('連結失敗');
      }else{
          console.log('連結成功');   
      }
    });//連結資料庫名Mangagement埠號27017,取消資料庫啟動警告,
    
    app.listen(port,()=>{
              console.log(`Example app listening at http://localhost:${port}`)
          })
    

    開啟資料庫
    在安裝mongodb/bin目錄執行cdm
    執行如下指令

    $ mongod  --dbpath="資料庫路徑" --port=埠號
    //例如
    $ D:\Mongodb\bin> mongod  --dbpath="E:\myNode\Management\db" --port=27021

    然後再E:\myNode\Management執行

    nodemon app.js//如果成功控制檯會列印
    連結成功
    Example app listening at http://localhost:8080
    //說明資料庫連結成功

    連結成功我們可以對MongoDB資料庫進行CURD操作
    在schema資料夾下定義資料表模式型別
    在schema/user.js

    const mongoose=require('mongoose');
    module.exports=new mongoose.Schema({
      Mailbox:String,
      UserName:String,
      Password:String,
      Password01:String,
      Name:String,
      Phone:Number,
      ContactAddress:String,
      Passport:String,
      ID:Number,
      Company:String,
      TouristGuide:String,
      GoAbroad:String
    })

    在model資料夾定義資料表模型

    const mongoose=require('mongoose');
    const userSchema=require('../schema/user.js')
    module.exports=mongoose.model('User',userSchema)
    //定義資料表名為User但是mongodb中的資料表名是Users

    在route資料夾下定義路由

    const express=require('express');
    const multipart = require('connect-multiparty');//
    const XLSX=require("xlsx")//讀取elsx檔案
    const multipartMiddleware = multipart();
    
    const router=express.Router();
    const User=require('../model/user.js')
    let userData;
    router.use((req,res,next)=>{
      UserData={
          code:0,
          data:{},
          message:""
      }
      next();
    })
    //上傳excal表
    router.post('/uploadFile', multipartMiddleware, async function (req, res, next) {
      console.log("成功")
      console.log(req.files.file.path)
     let excelData = [];   //用來儲存
     let reqData = [];
     const workbook = XLSX.readFile(req.files.file.path);//讀取檔案
     console.log(workbook)
    
     const sheetNames = workbook.SheetNames;//[sheet1]
    for (var sheet in workbook.Sheets) {
        console.log(sheet)
      if (workbook.Sheets.hasOwnProperty(sheet)) {
        fromTo = workbook.Sheets[sheet]['!ref'];
        console.log(workbook.Sheets[sheet])
        console.log(fromTo)
        //解析excel檔案得到資料
        excelData = excelData.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));
      }
    }
    //excel表日期處理方法
    function excelDateFN(DataStr){
        var y = new Date(1900, 0, DataStr)
        var d=new Date(y)
        var m=d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate() 
        //+ ' ' + d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds(); 
        return m
    }
     console.log(excelData);
    for (var i = 0; i < excelData.length; i++) {
      reqData.push({
        id: excelData[i]['編號'],
        Name: excelData[i]['姓名'],
        Sex: excelData[i]['性別'],
        EName: excelData[i]['英文名'],
        Nationality: excelData[i]['國籍'],
        BirthPlace: excelData[i]['出生地點'],
        BirthDay: excelDateFN(excelData[i]['出生日期']),
        Passport: excelData[i]['護照號'],
        DateIssue: excelDateFN(excelData[i]['護照簽發日期']),
        PeriodValidity: excelDateFN(excelData[i]['護照有效期']),
        PlaceIssue: excelData[i]['護照簽發地'],     
        Visa: excelData[i]['簽證號碼'],
      })
    }
    //資料處理結束呼叫sql語句,並且返回前臺
     console.log(reqData);
     if(reqData.length!=0){
         UserData.code=1;
         UserData.message="上傳成功";
         UserData.data=reqData
         res.send(UserData)
     }else{
         UserData.code=1;
         UserData.message="上傳失敗";
         UserData.data=""
         res.send(UserData)
     }
    //res.json(reqData)
    
     
    })
    
    //資訊展示
    router.post("/personalData",(req,res)=>{
      const UserName=req.body.UserName
      
      User.findOne({UserName:UserName}).then((data)=>{
          if(data){
              UserData.code=1;
              UserData.message="請求成功";
              UserData.data=data
              res.send(UserData)
          }
          
      })
      
    })
    //修改資訊
    router.post("/revisePersonalData",(req,res)=>{
      console.log(req.body)
      const _id=req.body._id,
          UserName=req.body.UserName,
          Password=req.body.Password,
          Password01=req.body.Password01,
          Name=req.body.Name,
          Phone=req.body.Phone,
          ContactAddress=req.body.ContactAddress,
          Passport=req.body.Passport,
          ID=req.body.ID,
          Company=req.body.Company
      const updateFields = {
                      _id,
                      UserName,
                      Password,
                      Password01,
                      Name,
                      Phone,
                      ContactAddress,
                      Passport,
                      ID,
                      Company
                              };
      User.findByIdAndUpdate({_id:_id},updateFields,(err,data)=>{
          if(data){
              UserData.code=1;
              UserData.message="修改成功";
              
              res.send(UserData)
          }
      })
      
        
    })
    //註冊
    router.post('/logon',(req,res)=>{
          const UserName=req.body.UserName
          const Password=req.body.Password
          const Password01=req.body.Password01
          const Name=req.body.Name
          const Phone=req.body.Phone
          const ContactAddress=req.body.ContactAddress
          const Passport=req.body.Passport
          const ID=req.body.ID
          const Company=req.body.Company
      //console.log(req.body)
      User.findOne({UserName:UserName}).then(function(data){
          console.log(data)
          if(data){
              UserData.code=3;
              UserData.message="使用者名稱已存在";
              res.send(UserData)
          }else{
              let newUser=new User({
                  UserName:UserName,
                  Password:Password,
                  Password01:Password01,
                  Name:Name,
                  Phone:Phone,
                  ContactAddress:ContactAddress,
                  Passport:Passport,
                  ID:ID,
                  Company:Company,    
              })
               newUser.save()
               UserData.code=1;
               UserData.message="註冊成功";
               res.send(UserData)
          }
      })
      
    })
    //登入
    router.post('/register',(req,res)=>{
      let userName=req.body.userName;
      let password=req.body.passWord;
       console.log(req.body)
      User.find({UserName:userName,Password:password}).then((data)=>{
          console.log(data)
          if(data){
              console.log('登入成功')
              UserData.code=1
              UserData.message="登入成功"
              res.send(UserData)
          }else{
              console.log('登入成功')
              UserData.code=2
              UserData.message="使用者名稱不存在"
              res.send(UserData)
          }
      })
      
    })
    module.exports=router

    在app.js中使用路由

    app.use('/User',require('./route/user.js'))

    介面:
    註冊:http://localhost:8080/User/login
    登入:http://localhost:8080/User/re...
    上傳:http://localhost:8080/User/up...
    查詢:http://localhost:8080/User/pe...
    修改:http://localhost:8080/User/re...

  • 在Koa中
    首先初始化專案

    npm init //初始化專案
    npm i xxx --save//安裝各種依賴例如koa nodemon ...

    目錄如下

    |-koa
    |  | -- db//啟動mongodb資料庫的dbpath路徑
    |  | --model//資料庫中表的模型
    |  | --node_modules
    |  | --public//公共資源
    |  | --route//路由
    |  | --schema//模式型別
    |  | --app.js//入口檔案
    |  | --package.json//配置檔案

    安裝mongoose。

    npm install mongoose//安裝mongoose

    在package.json

    {
    "name": "vietnam",
    "version": "1.0.0",
    "description": "越南簽證管理系統的介面專案",
    "main": "index.js",
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
      "start": "node app.js"
    },
    "author": "慄路遙",
    "license": "ISC",
    "dependencies": {
      "@koa/multer": "^3.0.0",
      "koa": "^2.13.1",
      "koa-body": "^4.2.0",
      "koa-bodyparser": "^4.3.0",
      "koa-router": "^10.0.0",
      "koa-static": "^5.0.0",
      "koa2-cors": "^2.0.6",
      "mongodb": "^4.0.1",
      "mongoose": "^5.13.5",
      "multer": "^1.4.2",
      "path": "^0.12.7"
    },
    "devDependencies": {}
    }
    
    

    在app.js中引入依賴

    const Koa=require('koa');
    const cors = require('koa2-cors');//跨域的包
    const mongoose=require('mongoose');
    const router=require('koa-router')()//路由
    const koaStatic=require('koa-static')//靜態
    const koaBody=require('koa-body');//
    const multer = require('@koa/multer');
    const bodyParser=require('koa-bodyparser')//post請求
    const path=require('path');
    const app=new Koa();
    
    
    var storage = multer.diskStorage({
      //檔案儲存路徑
      destination: function(req, file, cb) {
          cb(null,path.join(__dirname ,'/public/uploads'))
      },
      //修改檔名稱
      filename: function(req, file, cb) {
          let type = file.originalname.split('.')[1]
          cb(null, `${file.fieldname}-${Date.now().toString(16)}.${type}`)
      }
    })
    //載入配置
    //
    
    var upload = multer({storage});
    router.post('/upload',upload.single('File'), async(ctx, next) => {
      console.log(ctx.request)
    ctx.body = `${ctx.origin}/public/uploads/${ctx.file.filename}`
    })
    
    let register=require('./routes/register.js')
    let vise=require('./routes/visa.js')
    let DataList=require('./routes/datalist.js')
    router.use(register.routes())//登入介面
    router.use(vise.routes())//簽證介面
    router.use(DataList.routes())
    app.use(cors())//允許跨域
    
    app.use(bodyParser())//啟用bodyParser解決post請求
    app.use(router.routes())//啟用路由
    app.use(router.allowedMethods()) 
    mongoose.connect('mongodb://localhost:27018/VietNam',{useNewUrlParser:true,useUnifiedTopology:true},(err)=>{
      if(err){
          console.log('連結失敗');
      }else{
          console.log('連結成功');    
          {
              //建立新表
              //const dataList=mongoose.model('資料表名',{"健名":型別})
              //const kitty = new dataList({"鍵名":"鍵值"})
              //kitty.save().then(() => console.log('我是建立資料新表'));
          }
          
      };
      })//資料表名VietNam埠號27018取消資料庫啟動警告
    app.listen(3001,()=>{
      console.log('http://localhost:3001')
    });

    開啟資料庫
    在安裝mongodb/bin目錄執行cdm
    執行如下指令

    $ mongod  --dbpath="資料庫路徑" --port=埠號
    //例如
    $ D:\Mongodb\bin> mongod  --dbpath="E:\myNode\VietNam\db" --port=27018

    然後再E:\myNode\Management執行

    nodemon app.js//如果成功控制檯會列印
    連結成功
    http://localhost:3001
    //說明資料庫連結成功

    連結成功我們可以對MongoDB資料庫進行CURD操作
    在schema資料夾下定義資料表模式型別
    在schema/user.js

    //和express使用方法一樣
    const mongoose=require('mongoose');
    module.exports=new mongoose.Schema({
      UserName:String,
      Password:String,
    })

    在model資料夾定義資料表模型

    //和express使用方法一樣
    const mongoose=require('mongoose');
    const userSchema=require('../schema/user.js')
    module.exports=mongoose.model('User',userSchema)
    //定義資料表名為User但是mongodb中的資料表名是Users

    在route資料夾下定義路由

    const Router=require('koa-router');
    const router=new Router();
    const Visa=require('../model/visa.js');
    router.post('/visa',async (ctx,next)=>{
      console.log(ctx.request.body.ID)
      ctx.response.status=200
      let VisaU= await Visa.find({"ID":ctx.request.body.ID})
      const obj={
          detail:[]
      }
      let User=VisaU[0]    
      console.log(User)
      if(User===undefined){
          //obj.msg="該訂單不存在"
          ctx.body=obj
      }else{
          //obj.msg="查詢成功"
          obj.detail=User
          ctx.body=obj
          
      }
      //ctx.body=User
    })
    module.exports=router

    在app.js中使用路由

    let vise=require('./routes/visa.js')
    router.use(vise.routes())//簽證介面

    介面:
    簽證:http://localhost:8080/visa

  • 在Egg中
    首先初始化專案

    $ mkdir project-name//建立一個空的資料夾
    $ npm init egg --type=simple//simple表示骨架型別

    目錄如下:

    |-app//主要開發的檔案
    |   |-- controller//解析使用者的輸入,處理後返回相應的結果
    |   |-- db//啟動mongodb資料庫的dbpath路徑(可選)
    |   |--extend//框架的擴充套件(內建物件擴充套件)
    |   |    |---application.js//(固定名稱)
    |   |    |---context.js//(固定名稱)
    |   |    |---request.js//(固定名稱)
    |   |    |---response.js//(固定名稱)
    |   |    |---helper.js//(固定名稱)
    |   |--middleware//編寫中介軟體
    |   |--model//資料庫中表的模型
    |   |--publie//靜態資源
    |   |--schedule//定時任務
    |   |--service//編寫業務邏輯層
    |   |--view//模板檔案
    |   |---router.js//配置 URL 路由
    |-config//存放配置檔案
    |   |--config.default.js//用於編寫配置檔案
    |   |--plugin.js//配置需要載入的外掛
    |-test//存放單元測試
    |-logs//日誌檔案
    |-package.json//專案描述

    下載egg-mongoose

    npm i egg-mongoose --save

    配置config/plugin.js

    'use strict';
    module.exports = {
    mongoose:{
       enable:true,
       package:"egg-mongoose" 
    }
    };

    在config/config.default.js

    'use strict';
    module.exports = appInfo => {
    const config = exports = {};
    // use for cookie sign key, should change to your own and keep security
    config.keys = appInfo.name + '_1641975352438_173';
    // add your middleware config here
    config.middleware = [];
    // add your user config here
    const userConfig = {
      // myAppName: 'egg',
    };
     
     //mongoose資料庫配置
    config.mongoose={
        url:'mongodb://127.0.0.1:27021/VietNamVisa',//埠號27021資料庫名VietNamVisa
        options:{useNewUrlParser:true,useUnifiedTopology:true},//其他配置警告解除方法
    }
    
    return {
      ...config,
      ...userConfig,
    };
    };

    開啟資料庫

開啟電腦上的mongodb資料夾下的bin目錄cmd
執行mongod --dbpath=儲存資料的路徑 --port=資料庫的埠號
例如

mongod  --dbpath=E:\myNode\VietNamVisa\init\app\db    --port=27021

然後再E:\myNode\VietNamVisa執行

 npm run dev//啟動專案

在app/model/visaOnArrivalModel.js
建立一個模型

module.exports=app=>{
    const {mongoose}=app;
    const {Schema}=mongoose;
    const VisaOnArrivalSchema=new Schema({
        //訂單號
        OrderNumber:{type:String},
        //姓名
        FullName:{type:String},
        //護照號
        PassportNo:{type:String},
        //出發航班號
        DepartureFlightNumber:{type:String},
        //入境時間
        TimeOfEntry:{type:String},
        //抵達機場
        ArriveAtTheAirport:{type:String},
        //航班號
        FlightNumber:{type:String},
        //英文名
        EnglishName:{type:String},
        //性別
        Gender:{type:String},
        //出生日期
        DateOfBirth:{type:String},
        //國籍
        Nationality:{type:String},
        //護照簽發日期
        PassportIssueDate:{type:String},
        //護照有效期
        PassportPeriodOfValidity:{type:String},
        //離境日期
        DepartureDate:{type:String},
        //出發城市
        DepartureCity:{type:String},
        //批文型別
        Type:{type:String},
        //批文的狀態
        Status:{type:String},
        //Checked:{type:Boolean}
    });
    return mongoose.model("VisaOnArrivalModel",VisaOnArrivalSchema,"visaonarrivals")
    }
//定義了一張名為visaonarrivals的資料表

在app/service/visaOnArrivalService.js
寫運算元據庫的業務邏輯

"use strict"
const Service=require("egg").Service;
class VisaOnArrivalService extends Service {
    async VisaOnArrival(obj){
        const {ctx}=this;
        
            //儲存資料
            //注意!!!!ctx.model.xxx中xxx指的是model的檔名首字母大寫
         const VisaOnArrivalList = new ctx.model.VisaOnArrivalModel({
                        OrderNumber:obj.OrderNumber,
                         //姓名
                        FullName:obj.FullName,
                        //護照號
                        PassportNo:obj.PassportNo,
                        //出發航班號
                        DepartureFlightNumber:obj.DepartureFlightNumber,
                        //入境時間
                         TimeOfEntry:obj.TimeOfEntry,
                        //抵達機場
                        ArriveAtTheAirport:obj.ArriveAtTheAirport,
                        //航班號
                        FlightNumber:obj.,
                        //英文名
                         EnglishName:obj.FlightNumber,
                         //性別
                         Gender:obj.Gender,
                        //出生日期
                        DateOfBirth:obj.DateOfBirth,
                         //國籍
                         Nationality:obj.Nationality,
                        //護照簽發日期
                         PassportIssueDate:obj.PassportIssueDate,
                         //護照有效期
                        PassportPeriodOfValidity:obj.PassportPeriodOfValidity,
                         //離境日期
                         DepartureDate:obj.DepartureDate,
                       //出發城市
                         DepartureCity:obj.DepartureCity,
                         //型別
                         Type:obj.Type,
                         //批文的狀態
                        Status:obj.Status,              
                     });
                   // 資料儲存到資料庫
                    VisaOnArrivalList.save();
                    return "新增成功"
                    }
    
}
module.exports=VisaOnArrivalService;

在app/controller/visaOnArrival.js
下編寫關於解析使用者的輸入,處理後返回相應的結果

"use strict"
const Controller=require('egg').Controller;
class VisaOnArrival extends Controller {
    async VisaOnArrival(){
        const {ctx}=this
        //const req=ctx.request.body
        const res=await ctx.service.visaOnArrivalService.VisaOnArrival(req)
        //console.log(res)
        ctx.body={
            state:200,
            msg:res
        }
    }
}
module.exports=VisaOnArrival

在app/router.js
編寫路由

'use strict';
module.exports = app => {
  const { router, controller } = app;
 //新增資料
  router.post("/AddVisaOnArrival",controller.visaOnArrival.VisaOnArrival);
};

總結

以上就是關於Mongoose在Express、Koa、 Egg中使用對比,Mongoose在Express、Koa的使用沒有區別。在 Egg中的使用相較與另外兩個框架有較大的改動。最大的區別還是基於框架自身特點。前兩個框架沒有太多約定,寫法比較自由隨性,完全根據開發者自己的喜好編寫。Egg的特點約定優於配置。開發者書寫就更加規範統一。

相關文章