专栏首页小丑的小屋深入浅出mongodb之实战

深入浅出mongodb之实战

人的一生就像一篇文章,只有经过多次精心修改,才能不断完善。

前言

再好的东西不使用它,他终究不属于你,只有我们真正的把它运用到实际,真正的理解它,才能发挥它的最大作用正所谓实践出真理深入浅出mongodb(一)深入浅出mongodb(二)两篇文章讲述了一些安装和使用的基础知识,这篇文章小编将带你走进实战世界,真正体会项目中是怎么使用mongodb开发,让我们一起揭开它神秘的面纱。

准备工作

项目中我们用到的是基于nodeexpress[1] 框架

npm i express-generator -g

express-generator是一个express的应用生成器,可以快速的创建一个express应用。

安装完成上述指令之后,我们可以检查一下安装的express是否能用

express --version

接着我们就可以创建项目了,在创建项目的时候可以先express -h来查看一下,express命令的参数

$ express -h

  Usage: express [options] [dir]

  Options:

        --version        output the version number
    -e, --ejs            add ejs engine support
        --pug            add pug engine support
        --hbs            add handlebars engine support
    -H, --hogan          add hogan.js engine support
    -v, --view <engine>  add view <engine> support (dust|ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
        --no-view        use static html instead of view engine
    -c, --css <engine>   add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
        --git            add .gitignore
    -f, --force          force on non-empty directory
    -h, --help           output usage information

在默认的情况下,我们创建的项目模板引擎使用的是jade,个人感觉ejs[2]模板引擎比较好用,所以我们可以通过修改模板引擎的方式创建项目

express backend -e

创建好项目之后,我们express骨架已经搭建好了,我们可以启动项目看一下效果

cd backend
npm i
npm start

如果出现下面的结果说明我们的启动成功了

$ npm start

> backend@0.0.0 start C:\Users\DELL\Desktop\backend
> node ./bin/www

这个时候我们打开项目先熟悉一下项目目录

  • bin是启动目录,里面有一个www启动文件,默认的端口是3000,如果不合适我们可以手动修改
  • node_modules这个目录下面是我们安装的所有依赖
  • pubilc这个文件夹下是我们前端存放静态资源的
  • routes这个文件是存放路由的,主要编写前端发送请求和响应数据给前端
  • views这个文件夹中ejs文件结尾的文件是后端的模板文件
  • app.js是入口文件,模板配置和总路由文件
  • package.json 这个是包的描述文件,我们主要关注的是scriptsdependencies

我们在执行node文件的时候,如果修改了node文件,每次执行都需要重新启动项目才行,为了方便我们可以使用nodemon来监听项目的改动,不再需要重复启动项目,这么方便的东西用起来能不香吗??

npm i nodemon -g
//package.json
"scripts": {
    "start": "nodemon ./bin/www"
 },

完成上述的操作之后,我们启动项目npm start

数据库

安装

npm i mongoose -S

完成安装之后我们需要在app.js里引入并且配置数据库

//app.js
//引入数据库
const mongoose = require('mongoose');
//连接数据库
mongoose.connect(`mongodb://localhost:27017/test`,{
        useNewUrlParser: true,
        useUnifiedTopology: true 
});

设置跨域

在开发中,我们采用的都是前后端分离的状态,在本地的开发环境中我们无法避免的会遇到跨域[3]的情况,我们这里设置允许所有的源访问

app.use("/*", function (req, res, next) {
  //设置headers
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTION");
  //自定义请求头
  res.header(
    "Access-Control-Allow-Headers",
    "Content-type,Accept,X-Access-Token,X-Key"
  );
  if (req.method == "OPTIONS") {
    res.status(200).end();
  } else {
    next();
  }
});

OPTIONS这个是预检请求,如果遇到了不同源请求时,会先询问来自哪个源对源进行检查之后,做出响应。

实际上在真正的开发环境中,如果我们这么设置允许所有的的源都可以访问会有很多问题,我们可以使用cors[4]来代替它

当然如果在生产中我们采用nginx部署之后,就不存在跨域了?

接下来就是我们平时常说的mvc模式下的mc部分了,为了结构清晰,便于维护我们分成四部分scheme,model,controller,api

scheme

在项目的根目录下创建scheme文件夹,因为这里项目简单我们就创建一个index.js文件,当然如果项目模块和功能比较多的话,我们可以按照功能来创建文件,因人而异。

const mongoose = require("mongoose");
const Scheme = mongoose.Schema;

const ObjectId = mongoose.Types.ObjectId;

//物品表
const gooseScheme = Scheme({
  id: ObjectId,
  name: String,
  age: Number,
  image: String,
  price: Number,
  description: String,
  user: {
    type: ObjectId,
    ref: "User",
  },
});

//用户表
const  userScheme= Scheme({
  id: ObjectId,
  name: String,
});

module.exports = { gooseScheme, userScheme };

model

在项目的根目录下创建model的文件夹,创建index.js文件:

const mongoose = require("mongoose");
const model = mongoose.model.bind(mongoose);
const scheme = require("../scheme");

const { gooseScheme, userScheme } = scheme;

const GooseModel = model("Goose", gooseScheme);
const UserModel = model("User", userScheme);

module.exports = { GooseModel, UserModel };

controller

在项目的根目录下创建controller的文件夹,根据功能我们创建userController.jsgooseController.js

//userController.js
const Model = require("../model");
const { UserModel } = Model;

const userController = {
  all(req, res) {
    UserModel.find({}).then(docs => res.json(docs));
  },
  create(req, res) {
    const requestBody = req.body;
    const newUserModel = new UserModel(requestBody);

    newUserModel.save((err, save) => {
      UserModel.findOne({ _id: save._id }).then((docs) => res.json(docs));
    });
  },
  byId(req, res) {
    const idParams = req.params.id;

    UserModel.findOne({ _id: idParams }).then((docs) => res.json(docs));
  },
  update(req, res) {
    const idParams = req.params.id;
    let requestBody = req.body;

    UserModel.updateOne({ _id: idParams }, { ...requestBody }, (err, docs) => {
      res.json(docs);
    });
  },
  remove(req, res) {
    const idParams = req.params.id;

    UserModel.findOne({ _id: idParams }).remove((err, docs) =>
      res.json(idParams)
    );
  },
};

module.exports = userController;

//gooseController.js
const Model = require("../model");
const { GooseModel } = Model;

const gooseController = {
  all(req, res) {
    GooseModel
      .find({})
      .populate("user")
      .then(docs=> res.json(docs));
  },
  byId(req, res) {
    const idParams = req.params.id;

    GooseModel
      .findOne({ _id: idParams })
      .populate("user")
      .then((docs) => res.json(docs));
  },
  create(req, res) {
    const requestBody = req.body;
    const newGooseModel = new GooseModel(requestBody);

    newGooseModel.save((err, saved) => {
        console.log(saved);
        GooseModel
        .findOne({ _id: newGooseModel._id })
        .populate("user")
        .then((docs) => res.json(docs));
    });
  },
  update(req, res) {
    const idParams = req.params.id;
    const requestBody = req.body;

    GooseModel.updateOne({ _id: idParams }, { ...requestBody }, (err, docs) => {
      res.json(docs);
    });
  },
  remove(req, res) {
    const idParams = req.params.id;

    gooseModel
      .findOne({ _id: idParams })
      .remove((err, docs) => res.json(idParams));
  },
};

module.exports = gooseController;

api

在express中有这么一句话一切皆为中间件,我们在设置路由的时候,需要在app.js中注册之后才能使用

//app.js
var api = require("./routes/api");
app.use("/api",api)

配置routes文件夹下的api.js文件

const express = require("express");
const router = express.Router();

const gooseController = require("../controller/gooseController");
const userContoller = require("../controller/userController");

router.get('/user',userContoller.all);
router.get('/user/:id',userContoller.byId);
router.post('/user', userContoller.create);
router.put('/user/:id', userContoller.update);
router.delete('/user/:id', userContoller.remove);


router.get('/goose', gooseController.all);
router.get('/goose/:id', gooseController.byId);
router.post('/goose', gooseController.create);
router.put('/goose/:id', gooseController.update);
router.delete('/goose/:id', gooseController.remove);

module.exports = router

成果

我们完成上面的步骤之后,我们需要自测试一下接口和逻辑是否正确

查询人员

localhost:3000/api/user get

新增人员

localhost:3000/api/user post

删除人员

localhost:3000/api/user/:id delete

新增物品

localhost:3000/api/goose post

查询物品及所属人员

localhost:3000/api/goose get

最后

本文结束,有什么问题和有错误的地方,欢迎大家的留言和评论,还有后续更新,下期更加精彩 ???

参考资料

[1]

express: https://www.expressjs.com.cn/

[2]

ejs: https://ejs.bootcss.com/

[3]

跨域: http://www.ruanyifeng.com/blog/2016/04/cors.html

[4]

cors: https://www.npmjs.com/package/cors

本文分享自微信公众号 - 小丑的小屋(clownjack2020),作者:萌新小丑

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-08-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 深入浅出mongodb(一)

    在大数据的驱使下,我们要实现数据持久化存储,数据共享,数据集中管理数据库是不二之选,小编在这里要阐述的是 mongodb 数据库,mongodb[1]是一个基于...

    小丑同学
  • 如何让一个字符串执行?

    虽然eval()函数有这个功能但是我们还是避而远之,能不用尽量不要用。eval的执行环境比较混乱,它会查找当前执行的上下文环境从而导致混乱。

    小丑同学
  • [不定时一题]Leetcode两数之和

    今天又是神奇的一天,今天是小编默默的打开了Leetcode题库的第一天,初生牛犊不怕虎,开足马力就是干。

    小丑同学
  • FunDA(16)- 示范:整合并行运算 - total parallelism solution

       在对上两篇讨论中我们介绍了并行运算的两种体现方式:并行构建数据源及并行运算用户自定义函数。我们分别对这两部分进行了示范。本篇我准备示范把这两种情况集成一体...

    用户1150956
  • 一次搞懂滚动加载

    分页加载通常适用于客户端,通常是为了防止一次返回导致客户端崩溃,所以采用下拉加载更多的方式,为了防止数据重复的现象,数据传递建议使用唯一标识id。 普...

    用户5166556
  • TP踩过的坑【批量删除,(不涉及子栏目的批量删除)】

    简单、
  • [译] 不用祖传秘方 - 写好代码的几个小技巧

    原文:【The Non-Secret Formula for Writing Better Code】https://hackernoon.com/the-no...

    江米小枣
  • How does InnoDB behave without a Primary Key(11.InnoDB在没用主键情况下的行为)

    今天下午,我和Arjen Lentz讨论了InnoDB在没有声明主键的情况下的行为,这个话题很有趣,也没有足够的文档证明,所以有必要写一个简短的帖子。

    冬天里的懒猫
  • R的bioconductor包来批量得到芯片探针与gene的对应关系

    现有的基因芯片种类很多,但重要而且常用的芯片并不多,一般分析芯片数据都需要把探针的 ID 切换成基因的 ID。

    微点
  • 29. Vue 使用 vue-resource 发起post请求,删除列表数据

    定义数据列表为全局变量data_list,开发del_list视图函数根据id删除data_list数据,开发get_list读取data_list数据。

    Devops海洋的渔夫

扫码关注云+社区

领取腾讯云代金券