推广

Express,Sequelize和MySQL的Node.js Rest API示例

iseeyu2年前 (2024-02-22)推广130

http://localhost:8080

是的,第一步已经完成。 在下一节中,我们将与Sequelize一起协作。

配置MySQL数据库并进行序列化

在app文件夹中,我们创建一个单独的config文件夹,然后使用db.config.js文件进行配置,如下所示:

module.exports = {
  HOST: "localhost",
  USER: "root",
  PASSWORD: "123456",
  DB: "testdb",
  dialect: "mysql",
  pool: {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000
  }
};

前面5个参数用于MySQL连接。

pool是可选的,它将用于Sequelize连接池配置:

- max:池中的最大连接数
- min:池中的最小连接数
- idle:连接释放之前可以空闲的最长时间(以毫秒为单位)
- acquire:该池将在抛出错误之前尝试获取连接的最长时间(以毫秒为单位)

有关更多详细信息,请访API Reference for the Sequelize constructor。

初始化Sequelize

我们将在下一步包含模型的app/models文件夹中初始化Sequelize。

现在,使用以下代码创建app/models/index.js

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

const Sequelize = require("sequelize");
const sequelize = new Sequelize(dbConfig.DB, dbConfig.USER, dbConfig.PASSWORD, {
  host: dbConfig.HOST,
  dialect: dbConfig.dialect,
  operatorsAliases: false,

  pool: {
    max: dbConfig.pool.max,
    min: dbConfig.pool.min,
    acquire: dbConfig.pool.acquire,
    idle: dbConfig.pool.idle
  }
});

const db = {};

db.Sequelize = Sequelize;
db.sequelize = sequelize;

db.tutorials = require("./tutorial.model.js")(sequelize, Sequelize);

module.exports = db;

不要忘记在server.js中调用sync()方法

...
const app = express();
app.use(...);

const db = require("./app/models");
db.sequelize.sync();

...

在开发中,您可能需要删除现有表并重新同步数据库。 只需使用force:true即可,如下代码:

db.sequelize.sync({ force: true }).then(() => {
  console.log("Drop and re-sync db.");
});

定义Sequelize模型

在models文件夹中,像这样创建tutorial.model.js文件:

module.exports = (sequelize, Sequelize) => {
  const Tutorial = sequelize.define("tutorial", {
    title: {
      type: Sequelize.STRING
    },
    description: {
      type: Sequelize.STRING
    },
    published: {
      type: Sequelize.BOOLEAN
    }
  });

  return Tutorial;
};

该Sequelize模型表示MySQL数据库中的tutorials表。 这些列将自动生成:id, title, description, published, createdAt, updatedAt.

初始化Sequelize之后,我们无需编写CRUD函数,Sequelize支持所有这些功能:

  • 创建一个新的教程:create(object)
  • 通过id查找教程:findByPk(id)
  • 获取所有教程:findAll()
  • 通过id:update(data, where: { id: id })
  • 删除教程:destroy(where: { id: id })
  • 删除所有教程:destroy(where:{})
  • 按标题查找所有教程:findAll({ where: { title: … } })

这些功能将在我们的控制器中使用。

我们可以通过为每个教程添加评论来改进示例。 这是一对多关系,我为此编写了一个教程:
Sequelize Associations: One-to-Many example – Node.js, MySQL

或者,您可以为每个教程添加标签,并将教程添加到标签(多对多关系):
Sequelize Many-to-Many Association example with Node.js & MySQL

创建控制器

app/controllers文件夹中,让我们使用以下CRUD函数创建tutorial.controller.js:

  • create
  • findAll
  • findOne
  • update
  • delete
  • deleteAll
  • findAllPublised
const db = require("../models");
const Tutorial = db.tutorials;
const Op = db.Sequelize.Op;

// Create and Save a new Tutorial
exports.create = (req, res) => {
  
};

// Retrieve all Tutorials from the database.
exports.findAll = (req, res) => {
  
};

// Find a single Tutorial with an id
exports.findOne = (req, res) => {
  
};

// Update a Tutorial by the id in the request
exports.update = (req, res) => {
  
};

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

// Delete all Tutorials from the database.
exports.deleteAll = (req, res) => {
  
};

// Find all published Tutorials
exports.findAllPublished = (req, res) => {
  
};

让我们实现这些功能。

创建一个新对象

创建并保存一个新教程:

exports.create = (req, res) => {
  // Validate request
  if (!req.body.title) {
    res.status(400).send({
      message: "Content can not be empty!"
    });
    return;
  }

  // Create a Tutorial
  const tutorial = {
    title: req.body.title,
    description: req.body.description,
    published: req.body.published ? req.body.published : false
  };

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

检索对象(有条件)

从数据库中检索所有教程/按标题查找:

exports.findAll = (req, res) => {
  const title = req.query.title;
  var condition = title ? { title: { [Op.like]: `%${title}%` } } : null;

  Tutorial.findAll({ where: condition })
    .then(data => {
      res.send(data);
    })
    .catch(err => {
      res.status(500).send({
        message:
          err.message || "Some error occurred while retrieving tutorials."
      });
    });
};

我们使用req.query.title从Request中获取查询字符串,并将其作为findAll()方法的条件。

检索单个对象

查找具有ID的单个教程:

exports.findOne = (req, res) => {
  const id = req.params.id;

  Tutorial.findByPk(id)
    .then(data => {
      res.send(data);
    })
    .catch(err => {
      res.status(500).send({
        message: "Error retrieving Tutorial with id=" + id
      });
    });
};

更新对象

更新由请求中的id标识的教程:

exports.update = (req, res) => {
  const id = req.params.id;

  Tutorial.update(req.body, {
    where: { id: id }
  })
    .then(num => {
      if (num == 1) {
        res.send({
          message: "Tutorial was updated successfully."
        });
      } else {
        res.send({
          message: `Cannot update Tutorial with id=${id}. Maybe Tutorial was not found or req.body is empty!`
        });
      }
    })
    .catch(err => {
      res.status(500).send({
        message: "Error updating Tutorial with id=" + id
      });
    });
};

删除对象

删除具有指定id的教程:

exports.delete = (req, res) => {
  const id = req.params.id;

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

删除所有对象

从数据库中删除所有教程:

exports.deleteAll = (req, res) => {
  Tutorial.destroy({
    where: {},
    truncate: false
  })
    .then(nums => {
      res.send({ message: `${nums} Tutorials were deleted successfully!` });
    })
    .catch(err => {
      res.status(500).send({
        message:
          err.message || "Some error occurred while removing all tutorials."
      });
    });
};

按条件查找所有对象

查找所有published = true的教程:

exports.findAllPublished = (req, res) => {
  Tutorial.findAll({ where: { published: true } })
    .then(data => {
      res.send(data);
    })
    .catch(err => {
      res.status(500).send({
        message:
          err.message || "Some error occurred while retrieving tutorials."
      });
    });
};

可以对该控制器进行一些修改以返回分页响应:

{
    "totalItems": 8,
    "tutorials": [...],
    "totalPages": 3,
    "currentPage": 1
}

您可以在以下位置找到更多详细信息:
Server side Pagination in Node.js with Sequelize and MySQL

定义路由

当客户端使用HTTP请求(GET,POST,PUT,DELETE)发送对端点的请求时,我们需要通过设置路由来确定服务器的响应方式。

这些是我们的路由:

  • /api/tutorials:GET,POST,DELETE
  • /api/tutorials/:id:GET,PUT,DELETE
  • /api/tutorials/published:GET
    app/routes文件夹中创建一个turorial.routes.js,其内容如下:
module.exports = app => {
  const tutorials = require("../controllers/tutorial.controller.js");

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

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

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

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

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

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

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

  // Delete all Tutorials
  router.delete("/", tutorials.deleteAll);

  app.use('/api/tutorials', router);
};

您可以看到我们使用了/controllers/tutorial.controller.js中的控制器。

我们还需要在server.js中包含路由(在app.listen()之前):

...

require("./app/routes/turorial.routes")(app);

// set port, listen for requests
const PORT = ...;
app.listen(...);

测试API

使用以下命令运行我们的Node.js应用程序:node server.js
控制台显示:

Server is running on port 8080.
Executing (default): DROP TABLE IF EXISTS `tutorials`;
Executing (default): CREATE TABLE IF NOT EXISTS `tutorials` (`id` INTEGER NOT NULL auto_increment , `title` VARCHAR(255), `description` VARCHAR(255), `published` TINYINT(1), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `tutorials`
Drop and re-sync db.

使用Postman,我们将测试以上所有的Apis。

1、使用POST/tutorials Api创建一个新教程

Create a new Tutorial

创建一些新教程后,您可以检查MySQL表:

mysql> select * from tutorials;
+----+-------------------+-------------------+-----------+---------------------+---------------------+
| id | title             | description       | published | createdAt           | updatedAt           |
+----+-------------------+-------------------+-----------+---------------------+---------------------+
|  1 | JS: Node Tut #1   | Tut#1 Description |         0 | 2019-12-13 01:13:57 | 2019-12-13 01:13:57 |
|  2 | JS: Node Tut #2   | Tut#2 Description |         0 | 2019-12-13 01:16:08 | 2019-12-13 01:16:08 |
|  3 | JS: Vue Tut #3    | Tut#3 Description |         0 | 2019-12-13 01:16:24 | 2019-12-13 01:16:24 |
|  4 | Vue Tut #4        | Tut#4 Description |         0 | 2019-12-13 01:16:48 | 2019-12-13 01:16:48 |
|  5 | Node & Vue Tut #5 | Tut#5 Description |         0 | 2019-12-13 01:16:58 | 2019-12-13 01:16:58 |
+----+-------------------+-------------------+-----------+---------------------+---------------------+

2、使用GET /tutorials Api检索所有的教程

Retrieve all Tutorials

3、使用GET /tutorials/:id Api根据id查询单个教程

Retrieve a single Tutorial by id

4、使用`PUT /tutorials/:id’ Api更新教程

Update a Tutorial

在更新某些行后,请查看tutorials表:

mysql> select * from tutorials;
+----+-------------------+-------------------+-----------+---------------------+---------------------+
| id | title             | description       | published | createdAt           | updatedAt           |
+----+-------------------+-------------------+-----------+---------------------+---------------------+
|  1 | JS: Node Tut #1   | Tut#1 Description |         0 | 2019-12-13 01:13:57 | 2019-12-13 01:13:57 |
|  2 | JS: Node Tut #2   | Tut#2 Description |         0 | 2019-12-13 01:16:08 | 2019-12-13 01:16:08 |
|  3 | JS: Vue Tut #3    | Tut#3 Description |         1 | 2019-12-13 01:16:24 | 2019-12-13 01:22:51 |
|  4 | Vue Tut #4        | Tut#4 Description |         1 | 2019-12-13 01:16:48 | 2019-12-13 01:25:28 |
|  5 | Node & Vue Tut #5 | Tut#5 Description |         1 | 2019-12-13 01:16:58 | 2019-12-13 01:25:30 |
+----+-------------------+-------------------+-----------+---------------------+---------------------+

5、使用GET /tutorials?title=node查找标题包含’node’的所有教程

Find all Tutorials which title contains ‘node’

6、使用GET /tutorials/published Api查询所有已发布的教程

Find all published Tutorials

7、使用’DELETE /tutorials/:idApi删除一个教程 ![Delete a Tutorial](https://upload-images.jianshu.io/upload_images/15949040-921d6d926ec1ec72?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) id = 2的教程已从tutorials`表中删除:

mysql> select * from tutorials;
+----+-------------------+-------------------+-----------+---------------------+---------------------+
| id | title             | description       | published | createdAt           | updatedAt           |
+----+-------------------+-------------------+-----------+---------------------+---------------------+
|  1 | JS: Node Tut #1   | Tut#1 Description |         0 | 2019-12-13 01:13:57 | 2019-12-13 01:13:57 |
|  3 | JS: Vue Tut #3    | Tut#3 Description |         1 | 2019-12-13 01:16:24 | 2019-12-13 01:22:51 |
|  4 | Vue Tut #4        | Tut#4 Description |         1 | 2019-12-13 01:16:48 | 2019-12-13 01:25:28 |
|  5 | Node & Vue Tut #5 | Tut#5 Description |         1 | 2019-12-13 01:16:58 | 2019-12-13 01:25:30 |
+----+-------------------+-------------------+-----------+---------------------+---------------------+

8、使用’DELETE /tutorialsApi删除所有的教程 ![Delete all Tutorials](https://upload-images.jianshu.io/upload_images/15949040-e3fc6ce85574b9bc?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 现在在tutorials`表中没有一行数据了:

mysql> SELECT * FROM tutorials;
Empty set (0.00 sec)

结论

今天,我们已经学习了如何使用Express Web服务器创建Node.js Rest Apis。 我们还知道添加MySQL数据库和Sequelize配置,创建Sequelize模型,编写控制器以及定义用于处理所有CRUD操作的路由的方法。

您可以在下一个教程中找到更多有趣的东西:

  • Server side Pagination in Node.js with Sequelize and MySQL
    返回分页数据作为响应:
{
    "totalItems": 8,
    "tutorials": [...],
    "totalPages": 3,
    "currentPage": 1
}
  • Deploying/Hosting Node.js app on Heroku with MySQL database
    或者您可以将图像保存到MySQL数据库:
  • Upload/store images in MySQL using Node.js, Express & Multer

学习愉快! 再见。

进一步阅读

  • Express.js Routing
  • https://www.npmjs.com/package/express
  • https://www.npmjs.com/package/body-parser
  • https://www.npmjs.com/package/mysql2
  • Tutorials and Guides for Sequelize v5

将教程数据从文件上传到MySQL数据库表:
– Node.js: Upload Excel file data into MySQL Database
– Node.js: Upload CSV file data into MySQL Database

源代码

您可以在Github上找到此示例的完整源代码。

如果要为每个教程添加评论。 它是一对多关联,有一个有关该关系的教程:Sequelize Associations: One-to-Many example – Node.js, MySQL

或者,您可以为每个教程添加标签,并将教程添加到标签(多对多关系):
Sequelize Many-to-Many Association example with Node.js & MySQL

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/55938.html

相关文章

掌握网站优化的5种技巧。

掌握网站优化的5种技巧。

如今互联网时代,网络科技的发展让我们的生活发生了翻天覆地的变化,我们的企业和网站也凭借着这个红利快速发展,现在几乎每一个企业都会有自己的网站来进行宣传和推广。随着搜索引擎的不断升级,网站优化越来越难做,收益与付出越来越不成正比。那么需要掌握哪些网站优化的技巧呢? 第一,学会关键词的布局。关键词,是...

淘宝老店新开有扶持吗(淘宝店重开还有新店扶持吗)

淘宝老店新开有扶持吗(淘宝店重开还有新店扶持吗)

据了解,对于新开的淘宝店铺,淘宝有三个月的扶持期。不过,老店新开不一样,它基本已经不是新店而成为了老店,所以,是不能享受扶持的。...

上交所:拓宽境外资金参与交易所债券市场渠道

上交所:拓宽境外资金参与交易所债券市场渠道

6月28日,上交所联合中国结算发布境外机构投资者债券交易及登记结算业务实施细则,并自6月30日起施行。上交所表示,实施细则规范了境外机构投资者在上交所参与债券交易的相关行为,拓宽了境外机构投资者参与交易所债券的。下一步,上交所将持续完善各项债券交易制度安排,为境内外投资者提...

网站用户体验之使用。

网站用户体验之使用。

 使用这里强调的是网站的易用性和可用性,也就是用户在操作上的体验。一个网站的好坏,不单单是设计的高端大气,更多的还是易用性。网站好不好用,复不复杂,会直接决定你网站后期运营的效果。举几个网站易用性的例子吧,网站都会有文章页面,你的文章页面底部是否有上一篇OR下一篇?别小看这个功能,这个功能就是易用性...

运营管理笔记—企业如何做好渠道建设,渠道体系的搭建分为 ...

运营管理笔记—企业如何做好渠道建设,渠道体系的搭建分为 ...

在当下存量时代,若想获得新的增长机会,商家则需要寻找新的商业模式与方式,这其中便包括销售网络的建立,高效的渠道体系可以更好地帮助产品进行推广。企业在经营过程中,需要保证自身流量渠道的稳定性,以保障产品的销量和企业的日常经营。那么,如果渠道失灵,企业要如何找到适合自己的商业模...

实体门店如何写一个完整的营销策划方案

实体门店如何写一个完整的营销策划方案

1.阅读的三个建议本章的目的是实体门店如何写一个完整的活动方案,完整的不一定爆款方案,爆款方案一定完整的,所以先打好基本功才是根本,每个一炮而红都是蓄谋已久一个爆款活动是若干个小活动的积累,例如:粉丝积累,积累,转化能力,等等想、都是问题,做、才有答案2.实体门店做活动的几...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片