发布于 2026-01-06 5 阅读
0

MongoDB、Express、Vue 和 Node.js。index.js

MongoDB、Express、Vue 和 Node。

index.js

在之前的教程中,我们希望通过实践学习和理解无服务器、容器和服务器架构(https://dev.to/kevin_odongo35/serverless-container-or-server-approach-4mh5)。本教程将以循序渐进的方式,带您轻松愉快地学习和理解这些架构。

在今天的教程中,我们将介绍使用以下方法的第一种方法:

  1. 表达
  2. MongoDB // 我们也可以使用 MySQL、PostgreSQL 等。
  3. 节点

这就是我们试图实现的架构:

替代文字

在我们第一个教程中创建的目录(blog-vue-application)的根文件夹中。

替代文字

在根文件夹中运行以下命令:

$ mkdir blog-vue-back-end && cd blog-vue-back-end
$ npm init
package name: blog-vue-back-end
version: // press enter
description: Tutorial
entry point: index.js
test command: // press enter
git repository: // press enter
keywords: Mongo DB, Node, Passport and Express
author: your name
licence: MIT
// save
Enter fullscreen mode Exit fullscreen mode

完成后,安装以下软件包

  1. 表达
  2. 科尔斯
  3. 节点
  4. 正文解析器
  5. MongoDB // 将用于测试目的
  6. Jest // 您可以使用不同的测试方法
  7. dotenv
$ npm install express mongoose mongodb cors body-parser node express dotenv
Enter fullscreen mode Exit fullscreen mode

安装 nodemon 软件包作为依赖项,这样您就不必重启服务器了。

$ npm install -D nodemon
Enter fullscreen mode Exit fullscreen mode

以下是Node.js Express应用程序将导出的API:

方法 URL 行动
得到 api/blog 获取许多博客
得到 api/blog/:id 获取一个博客
邮政 api/blog 创建博客
api/blog 更新博客
删除 api/blog 删除许多博客
删除 api/blog/:id 删除单个博客

你的应用程序结构应该如下所示:

替代文字

package.json

安装完成后,请更新脚本的相应部分。您的 package.js 文件应该如下所示:

{
  "name": "blog-vue-back-end",
  "version": "1.0.0",
  "description": "Tutorial Backend for Blog Application",
  "main": "index.js",
  "scripts": {
    "start": "node server/index.js",
    "dev": "nodemon server/index.js",
    "test-dev": "jest"
  },
  "keywords": [
    "Mongo",
    "DB",
    "Express",
    "Node"
  ],
  "author": "Kevin Odongo",
  "license": "MIT",
  "dependencies": {
    "@shelf/jest-mongodb": "^1.2.3",
    "body-parser": "^1.19.0",
    "cors": "^2.8.5",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "jest": "^26.6.3",
    "mongodb": "^3.6.3",
    "mongoose": "^5.11.14"
  },
  "devDependencies": {
    "nodemon": "^2.0.7"
  }
}

Enter fullscreen mode Exit fullscreen mode

在后端文件夹中创建 index.js 文件。这将是我们应用程序的入口点。

$ touch index.js
Enter fullscreen mode Exit fullscreen mode

index.js

const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
require('dotenv').config()

const app = express();

// parse application/json
app.use(bodyParser.json())

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }))

var corsOptions = {
  origin: 'http://localhost:3000'
}
// use cors options
app.use(cors(corsOptions))

// 
const db = require("./app/models");
db.mongoose
  .connect(db.url, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useFindAndModify: false,
    useCreateIndex: true
  })
  .then(() => {
    console.log("Connected to the database!");
  })
  .catch(err => {
    console.log("Cannot connect to the database!", err);
    process.exit();
  });


// routes
const blog = require('./app/routes/blog')
app.use('/api/blog', blog)

// listening port
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}.`);
});
Enter fullscreen mode Exit fullscreen mode

一旦我们有了应用程序的入口点,就让我们初始化 MongoDB。

在根文件夹中创建一个名为 .env 的文件

$ touch .env
// add the following
MONGO_DB_URI = mongodb+srv://odongo:password@secretserver.e5kih.mongodb.net/blog?retryWrites=true&w=majority
Enter fullscreen mode Exit fullscreen mode

要获取您的 MongoDB URL,请在此处注册一个免费帐户:https://account.mongodb.com/account/register。注册后,创建集群、用户和数据库。

在 .gitignore 文件中添加 node 模块和 .env 文件。

$ touch .gitignore
// add the following
node_modules
# local env files
.env.local
.env.*.local
Enter fullscreen mode Exit fullscreen mode

创建一个名为 app 的目录,用于存放以下文件。

/app/config/db.config.js

从环境变量文件中暴露 MongoDB URI

module.exports = {
  url: process.env.MONGO_DB_URI
};
Enter fullscreen mode Exit fullscreen mode

/app/controller/blog.controller.js

在此目录中,我们将定义如何处理以下操作:

  1. 创造
  2. 查找所有
  3. 找到一个
  4. 更新
  5. 删除
  6. 全部删除
const db = require("../models");
const Blog = db.blog;

// Create and Save a new blog
exports.create = (req, res) => {
    // Validate request
  if (!req.body.content) {
    res.status(400).send({ message: "Content can not be empty!" });
    return;
  }

  // Create a blog
  const blog = new Blog({
    author: req.body.author,
    content: req.body.content,
    published: req.body.published ? req.body.published : false
  });

  // Save blog in the database
  blog
    .save(blog)
    .then(data => {
      res.send(data);
    })
    .catch(err => {
      res.status(500).send({
        message:
          err.message || "Some error occurred while creating the blog."
      });
    });

};

// Retrieve all blogs from the database.
exports.findAll = (req, res) => {
    const content = req.query.content;
    var condition = content ? { content: { $regex: new RegExp(content), $options: "i" } } : {};

    Blog.find(condition)
      .then(data => {
        res.send(data);
      })
      .catch(err => {
        res.status(500).send({
          message:
            err.message || "Some error occurred while retrieving blogs."
        });
      });

};

// Find a single blog with an id
exports.findOne = (req, res) => {
    const id = req.params.id;

    Blog.findById(id)
      .then(data => {
        if (!data)
          res.status(404).send({ message: "Not found blog with id " + id });
        else res.send(data);
      })
      .catch(err => {
        res
          .status(500)
          .send({ message: "Error retrieving blog with id=" + id });
      });

};

// Update a blog by the id in the request
exports.update = (req, res) => {
    if (!req.body) {
        return res.status(400).send({
          message: "Data to update can not be empty!"
        });
      }

      const id = req.params.id;

      Blog.findByIdAndUpdate(id, req.body, { useFindAndModify: false })
        .then(data => {
          if (!data) {
            res.status(404).send({
              message: `Cannot update Blog with id=${id}. Maybe Blog was not found!`
            });
          } else res.send({ message: "Blog was updated successfully." });
        })
        .catch(err => {
          res.status(500).send({
            message: "Error updating Blog with id=" + id
          });
        });

};

// Delete a blog with the specified id in the request
exports.delete = (req, res) => {
    const id = req.params.id;

    Blog.findByIdAndRemove(id)
      .then(data => {
        if (!data) {
          res.status(404).send({
            message: `Cannot delete Blog with id=${id}. Maybe Blog was not found!`
          });
        } else {
          res.send({
            message: "Blog was deleted successfully!"
          });
        }
      })
      .catch(err => {
        res.status(500).send({
          message: "Could not delete Tutorial with id=" + id
        });
      });

};

// Delete all blogs from the database.
exports.deleteAll = (req, res) => {
    Blog.deleteMany({})
    .then(data => {
      res.send({
        message: `${data.deletedCount} Blogs were deleted successfully!`
      });
    })
    .catch(err => {
      res.status(500).send({
        message:
          err.message || "Some error occurred while removing all blogs."
      });
    });
};

// Find all published blogs
exports.findAllPublished = (req, res) => {
    Blog.find({ published: true })
    .then(data => {
      res.send(data);
    })
    .catch(err => {
      res.status(500).send({
        message:
          err.message || "Some error occurred while retrieving blogs."
      });
    });
};
Enter fullscreen mode Exit fullscreen mode

/app/model/index.js

在这个目录中,我们将组装以下文件:

  1. /app/config/db.config
  2. /app/model/blog.model.js

请确保将此目录导入到您的索引文件中,并连接到您的 MongoDB。

const dbConfig = require("../config/db.config");

const mongoose = require("mongoose");
mongoose.Promise = global.Promise;

const db = {};
db.mongoose = mongoose;
db.url = dbConfig.url;
db.blog = require("./blog.model.js")(mongoose);

module.exports = db;
Enter fullscreen mode Exit fullscreen mode

/app/model/blog.model.js

我们的博客架构将位于此目录中。

module.exports = mongoose => {
    const Blog = mongoose.model(
      "blog",
      mongoose.Schema(
        {
          author: String,
          content: String,
          published: Boolean
        },
        { timestamps: true }
      )
    );

    // We can add a category to categorize articles

    // Incase you want to replace _.id with id 
    // schema.method("toJSON", function() {
    //   const { __v, _id, ...object } = this.toObject();
    //   object.id = _id;
    //   return object;
    // });

    // const Blog = mongoose.model("blog", schema);

    return Blog;
  };
Enter fullscreen mode Exit fullscreen mode

/app/routes/blog.js

这将处理我们所有的路由。请确保在 index.js 文件中导出此文件。

const express = require("express")
const router = express.Router()
const blog = require("../controller/blog.controller");

// /api/blog: GET, POST, DELETE
// /api/blog/:id: GET, PUT, DELETE
// /api/blog/published: GET

// Create a new blog
router.post("/", blog.create);

// Retrieve all blog
router.get("/", blog.findAll);

// Retrieve all published blog
router.get("/published", blog.findAllPublished);

// Retrieve a single blog with id
router.get("/:id", blog.findOne);

// Update a Tutorial with id
router.put("/:id", blog.update);

// Delete a Tutorial with id
router.delete("/:id", blog.delete);

// Create a new Tutorial
router.delete("/", blog.deleteAll);

module.exports = router
Enter fullscreen mode Exit fullscreen mode

现在后端已经准备就绪,我们可以将后端和前端集成起来。您可以使用 Postman 或任何其他工具来测试路由。

请记住,我们目前的路由尚未受到保护,因此不能直接上线生产环境。我们需要保护路由并为应用程序添加身份验证。下一篇文章将对此进行详细介绍。

在 VS Code 或你使用的任何文本编辑器的新窗口中打开你的前端目录,然后运行该应用程序。

$ cd .. && cd /blog-vue-front-end
$ npm run serve
// Your front-end will be running on PORT 8080 || PORT 8081
// Your back-end will be running on PORT 3000
Enter fullscreen mode Exit fullscreen mode

应用程序运行后,让我们在 components 文件夹中创建以下文件:

/components/mongo-express-script.js

这将包含我们对后端 mongo-express-script.js 的所有请求。

在前端安装axios

$ yarn add axios
Enter fullscreen mode Exit fullscreen mode

在 mongo-express-script.js 文件中添加以下内容:

import axios from "axios";

// create new blog
export const createnewblog = async item => {
  let data = {
    author: JSON.stringify({
      name: item.author.name,
      email: item.author.email,
      about: item.author.about
    }), // replace with auth user
    content: JSON.stringify({
      title: item.content.title,
      src: item.content.src,
      text: item.content.text
    })
  };
  let request = {
    url: "http://localhost:3000/api/blog", // should be replaced after going to production with domain url
    method: "post",
    headers: {
      "Content-type": "application/json"
    },
    data: JSON.stringify(data)
  };

  const response = await axios(request);
  return response;
};

// delete blog
export const deleteblog = async item => {
  let request = {
    url: "http://localhost:3000/api/blog/" + item, // should be replaced after going to production with domain url
    method: "delete",
    headers: {
      "Content-type": "application/json"
    }
  };

  const response = await axios(request);
  return response;
};

// update blog
export const updateblog = async item => {
  let data = {
    author: JSON.stringify({
      name: item.author.name,
      email: item.author.email,
      about: item.author.about
    }), // replace with auth user
    content: JSON.stringify({
      title: item.content.title,
      src: item.content.src,
      text: item.content.text
    }),
    published: item.published
  };
  let request = {
    url: "http://localhost:3000/api/blog/" + item._id, // should be replaced after going to production with domain url
    method: "put",
    headers: {
      "Content-type": "application/json"
    },
    data: JSON.stringify(data)
  };

  const response = await axios(request);
  return response;
};

// get all blog
export const retriveallblog = async () => {
  let request = {
    url: "http://localhost:3000/api/blog", // should be replaced after going to production with domain url
    method: "get",
    headers: {
      "Content-type": "application/json"
    }
  };

  const response = await axios(request);
  return response;
};


Enter fullscreen mode Exit fullscreen mode

以下是博客目前在您的后端配置下的运行方式。我们已完成集成。请确保您的后端和前端同时运行。

接下来呢?我们需要保护路由和身份验证,然后上线生产环境。

这是后端代码库:https://github.com/kevinodongo/tutorial-blog-backend.git

目前我们还没有投入生产环境,因此我们仍然可以采用容器或服务器方案。

谢谢

文章来源:https://dev.to/kevin_odongo35/mongodb-express-vue-and-node-2cml