从 0 开始使用 Sequelize 进行基础的数据库操作

本贴最后更新于 1354 天前,其中的信息可能已经渤澥桑田

官方文档:https://www.sequelize.com.cn/

使用 node.js 做后端是一个小项目中的任务,这篇文章是我不断踩坑后总结的内容。

如果官方文档有点看不懂,可以按照这篇文章做,从 0 开始搭建并使用 Sequelize 进行简单的数据操作。

开始

Sequelize 帮助我们便捷的操作数据库,在使用它之前,我们需要下好数据库,这里我是用 mysql 作为例子。

下载 mysql brew install mysql

启动 mysql mysql.serve start

如果需要进入 mysql 进行一些设置,可以 mysql -p

关闭 mysql mysql.serve stop

链接数据库设置

配置公共的数据表设置

可以作为一个单独的文件,在描述模型的时候引用该公共配置的实例。

// db.js const { Sequelize,Model } = require('sequelize'); const { dbName, host, port, user, password } = require('../config').db; // 引入配置好的数据库配置 const sequelize = new Sequelize(dbName, user , password, { dialect: 'mysql', // 数据库的配置 host, // 数据库的配置 port, // 数据库的配置 logging: false, // 或console.log, 是否输出sql语句 timezone: '+08:00', define:{ //create_time update_time delete_time timestamps: true, paranoid: true, createdAt: 'creationTime', updatedAt: 'updated_time', deletedAt: 'deleted_time', underscored: true, freezeTableName: true, } }); sequelize.sync({ // 每次初始化表是否删除原表 force: false, // 检查数据库中表的当前状态,进行必要的更改使其与模型匹配 alter: true }); module.exports = { sequelize }

配置数据库信息

在工作时,我们会有多个环境,比如测试环境、生产环境、本地环境。为了方便的使用配置,我们将三个环境的配置内容写在不同的文件中,在程序执行时根据运行环境读取对应的配置。

// const localConf = require('./local'); const devConf = require('./development'); const prodConf = require('./production'); let conf = localConf; if (process.env.NODE_ENV === 'production') { conf = prodConf; } if (process.env.NODE_ENV === 'development') { conf = devConf; } module.exports = conf;

配置信息举例。可以写成下面的形式,也可以直接是一个 json 文件。

module.exports = { env: 'local', db: { dbName: 'iconfont', host: '127.0.0.1', port: 3306, user: 'root', password: '12345678', }, auth: { authKey: 'eUnE#9~P', authPass: '*3mExsa}asd@#afSx;iPqwEqasvho;', }, oss: { cdn: "https://conan-test.oss-cn-beijing.aliyuncs.com", endpoint: "oss-cn-beijing-internal.aliyuncs.com", accessKeyId: "LTAIoRierLFA55aQ", accessKeySecret: "6T7jyq6UuE3wLZ69JwORltpySgEykB", domain: "https://oss-cn-beijing.aliyuncs.com", bucket: "conan-test", direct: 'conan-iconfont' } };

设计数据库表

设计数据库表的时候,需要明确好实体和关系。实体进作为描述实体,关系分为一对多关系和多对多关系,画出 ER 图。一对多关系,将多写在一的表里面;多对多关系,一定要建一个多对多关系表。

实体表删除是软删除,即没有真的删除,而是填充删除时间。对于关系表,则需要配置硬删除,即删除是真的从表中删除,不然在操作数据库的时候会有约束限制造成操作失败。

建立实体表,并建立一对多关系

假设:一个图集内包含多个图标,一个图标有一个唯一对应的图集。图标是一,图集是多,我们需要将图标的主键写在图集内。

图标数据表

const { sequelize } = require('../../core/db');// 引入公共数据表配置实例 const { Sequelize, Model } = require('sequelize'); class IconModel extends Model {} // 模型定义 IconModel.init({ id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true }, name: Sequelize.STRING, // 图标名称 svg: Sequelize.STRING(10240), // 图标内容<svg ..../> isPrivate: Sequelize.BOOLEAN // 是否私密的标记 }, { sequelize, tableName: 'icon' }); module.exports = { IconModel };

图集数据表

const { Sequelize, Model } = require('sequelize'); const { sequelize } = require('../../core/db'); const { IconModel } = require('./icon'); //引入图标数据表模型 class AtlasModel extends Model {} AtlasModel.init({ id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true }, name: Sequelize.STRING, // 图集名称 atlasPrefix: Sequelize.STRING, // 图标库前缀 fontOssUrl: Sequelize.STRING, // css文件cdn地址 isPrivate: Sequelize.BOOLEAN, // 是否私密 私密图集:true 公开图集:false }, { sequelize, tableName: 'atlas' }); // 定义关系 IconModel.belongsTo(AtlasModel); // 图标 属于 图集 ,会在数据库的图集表中存一个icon_model_id ,在代码中我们只需要调用函数,不需要关注这个细节,具体使用方法会在下面说清楚 AtlasModel.hasMany(IconModel); // 图集 有很多 图标 module.exports = { AtlasModel };

建立多对多关系

假设:一个项目内包含多个图标,每个图标也可以被不同的项目引用。多对多关系需要用一个单独的表描述。

(假如已经存在图标表 IconModel、项目表 ProjectModel)

多对多关系表

const { sequelize } = require("../../core/db"); const { Sequelize, Model } = require("sequelize"); const { IconModel } = require("./icon"); const { ProjectModel } = require("./project"); class IconProjectModel extends Model {} IconProjectModel.init( { id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true, }, }, { sequelize, paranoid: false, // 设置删除为硬删除。关系表必须设置这个,否则修改关联关系是会出错。(因为数据库的索引约束) tableName: "icon_project", } ); // 定义图标和项目的关系--- // 图标 对应 多个项目 IconModel.belongsToMany(ProjectModel, { through: IconProjectModel, as: "projects",// 对于icon模型来说,对应的项目的名字叫projects }); // 项目 对应 多个图标 ProjectModel.belongsToMany(IconModel, { through: IconProjectModel, as: "icons",// 对于项目模型来说,对应的项目的名字叫icons }); module.exports = { IconProjectModel };

与关系表有关的操作

基本的操作比较简单,这里不做赘述。较为不好懂的是关于关系表存取数据的操作。这里举几个例子,让大家快速理解如何使用。

相关文档:https://www.sequelize.com.cn/core-concepts/assocs#%E6%B7%BB%E5%8A%A0%E5%88%B0%E5%AE%9E%E4%BE%8B%E7%9A%84%E7%89%B9%E6%AE%8A%E6%96%B9%E6%B3%95

例一:通过项目 id,找到项目所有的图标。

const project = await ProjectModel.findByPK(87); const icons = await project.getIcons(); // 这样就取出来了所有的图标 const icons = await ProjectModel.getIcons(project); // 另一种写法 // 如果不想让返回的icons里面携带与icon相关的其他关系内容,可以输入参数 const icons = await project.getIcons({ joinTableAttributes: [], // 不携带关系表内容 attributes: { exclude: ["deleted_time", "AtlasModelId","creationTime","updated_time"] }, // 不携带删除时间和图集外键字段 });

例二: 更新项目中的图标

const newIcons = await IconModel.findAll({ where:{ name:{[Op.like]:'%icon1'} } )// 找出所有名称中含有icon1的图标 const project = await ProjectModel.findByPK(87); // 需要修改的项目 await project.setIcons(newIcons) // 重置关联关系 await project.addIcons(newIcons) // 增加关联关系 await project.removeIcons(newIcons) // 删除关联关系
1 操作
limanting 在 2021-08-09 16:08:44 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...