【Node.JS 数据库篇】Sequelize 的用法与mysql的关系

一、Sequlize是Node.JS中ORM实现

在 nodejs 中,「Sequlizejs」可能是最出类拔萃的 ORM 实现。植根于 nodejs,Sequlizejs 完美支持 Promise 式调用,进一步你可以走 async/await,和业务代码紧密粘合;如果上了 ts,从模型定义带来的类型提醒能让调用更省心。

表/模型的定义
ORM 的第一步就是要建立对象到数据表的映射,在 Sequlize 里是这样的,比如我们关联一个 station 的表
数据表station的定义

CREATE TABLE `station` ( 
`id` bigint(11) unsigned NOT NULL AUTO_INCREMENT, 
`store_id` varchar(20) NOT NULL DEFAULT '', 
`name` varchar(20) NOT NULL DEFAULT '', 
`type` tinyint(4) NOT NULL DEFAULT '0', 
`status` tinyint(4) NOT NULL DEFAULT '0', 
`ip` varchar(20) NOT NULL DEFAULT '', 
`related_work_order_id` bigint(20) NOT NULL DEFAULT '0', 
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 
`plate_no` varchar(20) NOT NULL DEFAULT '', 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='工位表';

Node.JS中station模型的定义

const Model = sequlize.define('station', { 
    id: { 
        field: 'id', 
        type: Sequelize.INTEGER, 
        allowNull: false, 
        primaryKey: true, 
        autoIncrement: true, 
    }, 
    store_id: Sequelize.STRING(20), 
    name: Sequelize.STRING(20), 
    type: Sequelize.TINYINT, 
    status: Sequelize.TINYINT, 
    ip: Sequelize.STRING(20), 
    plate_no: Sequelize.STRING(20), 
    related_work_order_id: Sequelize.BIGINT, 
});

二、Sequelize 执行基础的CRUD

Sequlize对象提供丰富的API,诸如:findOne、findAll、create、upsert、aggregate、max,文档/lib/model.js~Model里面安排的明明白白。

执行一个基本的CRUD
当我执行一个简单的CRUD:Station.findAll(),Sequlize转成的SQL是这样的:

SELECT 
    `id`, 
    `store_id`, 
    `name`, 
    `type`, 
    `status`, 
    `ip`, 
    `plate_no` 
FROM 
    `station` AS `station`;

三、Sequelize 执行复杂的CRUD

1. 指定字段attributes

Station.findAll({ 
    attributes: [ 'ip' ], 
    where: { 
        status: 1, 
    }, 
order: [ 
[ 'name', 'ASC' ], 
], 
limit: 10, 
offset: 5, 
});
SELECT `ip` FROM `station` AS `station` WHERE 
`station`.`status` = 1 ORDER BY `station`.`name` ASC LIMIT 5, 10;

2. 触发数据库事务

Station.findOrCreate({ 
    where: { 
        id: 1, 
    }, 
    defaults: { 
        name: 'haha', 
    }, 
});
START TRANSACTION; 
SELECT `id`, `store_id`, `name`, `type`, `status`, `ip`, `plate_no` FROM `station` AS `station` WHERE `station`.`id` = 2; 
INSERT INTO `station` (`id`,`name`) VALUES (2,`haha`); 
COMMIT;

3. LEFT JOIN 联表关系

一对一联表查询
一对一关系可用 belongsTo、hasOne 两种方式标记

// belongsTo:
File.BelongsTo(User, {
	foreignKey:'creator_id',	// File类的creatorId属性
	targetKey:'id',				// User类的id属性
});

// hasOne:
User.HasOne(File, {
	foreignKey:'creator_id',	// File类的creatorId属性
	sourceKey:'id',				// User类的id属性
});

事实上转换后的 SQL 也是一样的::LEFT JOIN::

# File.BelongsTo(User)
SELECT `file`.`id`, `user`.`id` AS `user.id`
FROM `file` 
    LEFT JOIN `user` ON `file`.`creator_id ` = `user`.`id`
# User.HasOne(File)
SELECT `user`.`id`, `file`.`id` AS `file.id`
FROM `user`
    LEFT JOIN `file` ON `user`.`id ` = `file`.`creator_id `

操作示例

// Task.belongsTo(User)

const tasks = await Task.findAll({ include: User });
console.log(JSON.stringify(tasks, null, 2));

// 结果
[{
  "name": "A Task",
  "id": 1,
  "userId": 1,
  "user": {
    "name": "张三",
    "id": 1
  }
},
{
  "name": "B Task",
  "id": 2,
  "userId": 2,
  "user": {
    "name": "李四",
    "id": 2
  }
}]

一对多联表查询

User.HasMany(File, { 
    foreignKey: 'creator_id',   // 如果不定义这个,也会自动定义为「源模型名 + 源模型主键名」即 user_id
    sourceKey: 'id',    // 源模型的关联键,默认主键,通常省略
}
// 这里 creator_id 位于目标模型 File 上

操作示例

// User.hasMany(Task);

const users = await User.findAll({ include: Task });
console.log(JSON.stringify(users, null, 2));

// 结果
[{
  "name": "张三",
  "id": 1,
  "tasks": [{
    "name": "A Task",
    "id": 1,
    "userId": 1
  }]
}]

多对多联表查询

User.BelongsToMany(Group, { 
    through: GroupUser,     // 
    foreignKey: 'group_id', // 如果不定义这个,也会自动定义为「目标模型名 + 目标模型主键名」即 user_id
    otherKey: 'user_id',
}

在这里插入图片描述

4. INNER JOIN 联表关系

预先加载时,可以强制查询仅返回具有关联模型的记录,通过 required: true 参数将查询从默认的 OUTER JOIN 转为 INNER JOIN

// User.hasMany(Task);

User.findAll({
  include: {
    model: Task,
    required: true
  }
});

5. 嵌套查询

嵌套列的顶级 WHERE 子句, Sequelize 引用嵌套列的方法:'$nested.column$', 可以用于将 where 条件从包含的模型从 ON 条件移动到顶层的 WHERE 子句

User.findAll({
  where: {
    '$Instruments.size$': { [Op.ne]: 'small' }
  },
  include: [{
    model: Tool,
    as: 'Instruments'
  }]
});

四、Sequlize常用方法和参数

1. findAll

// 从数据库读取整个表
const user = await User.findAll()
SELECT * FROM User;

// 选择某些特定属性
const user = await User.findAll({
	attributes:['name','age']
})
SELECT name,age FROM User;

// 重命名
User.findAll({
  attributes: ['name', ['age', 'ageage'], 'hats']
})
SELECT name, age AS ageage, hats FROM User;

// 使用聚合函数
User.findAll({
  attributes: {
    include: [
      [sequelize.fn('COUNT', sequelize.col('hats')), 'n_hats']
    ]
  }
})
SELECT name, age, ..., hats, COUNT(hats) AS n_hats FROM User;

// 使用聚合函数 + 部分属性字段
User.findAll({
  attributes: [
    'name',
    [sequelize.fn('COUNT', sequelize.col('hats')), 'n_hats'],
    'age'
  ]
})
SELECT name, COUNT(hats) AS n_hats, age FROM User;

// 排除部分字段
User.findAll({
  attributes: {
    include: [
      [sequelize.fn('COUNT', sequelize.col('hats')), 'n_hats']
    ],
    exclude: ['age']
  }
})
SELECT name, ..., hats, COUNT(hats) AS n_hats FROM User;

// 使用WHERE语句,and
User.findAll({
  where: {
    name: 'Tom',
    age: 20
  }
})
SELECT * FROM User WHERE name = 'TOM' AND age = 20;

// 使用WHERE语句,or
const { Op } = require('sequelize')
User.findAll({
  where: {
    [Op.or]: [
      { name: 'Tom' },
      { age: 20' }
    ]
  }
})
SELECT * FROM User WHERE name = 'TOM' OR age = 20;

// 分页限制 :跳过5行,然后获取10行
User.findAll({ offset: 5, limit: 10 })

2. count

// 查询 age = 20 的用户数量
const total = await User.count({
  where: {
    age: 20
  }
})

3. findByPk

findByPk 方法使用提供的主键从表中仅获得一行数据:

const user = await User.findByPk(1024) // 主键的值是 1024

4. findOne

findOne 方法获得它找到的 第一行 数据:

const user = await User.findOne({ where: { name: 'Tom' } })

5. findAndCountAll

结合了 findAll 和 count 的便捷方法。具体参考:findAndCountAll。findAndCountAll 方法返回有两个属性的对象:

  • count —— 整数,符合查询条件的记录总数
  • rows —— 数组对象,获得的记录
const { count, rows } = await User.findAndCountAll({
  where: {
    name: {
      [Op.like]: 'T%'
    }
  },
  offset: 10,
  limit: 2
})
console.log(count)
console.log(rows)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于在 Node.js 中使用 MySQL 进行增删改查操作,你可以使用以下步骤: 1. 首先,确保你已经安装了 `mysql` 模块。你可以通过在终端中运行以下命令来安装它: ``` npm install mysql ``` 2. 在你的 Node.js 代码中,引入 `mysql` 模块: ```javascript const mysql = require('mysql'); ``` 3. 创建与数据库的连接: ```javascript const connection = mysql.createConnection({ host: '数据库主机名', user: '用户名', password: '密码', database: '数据库名称' }); connection.connect((err) => { if (err) { console.error('数据库连接失败:', err); return; } console.log('数据库连接成功!'); }); ``` 4. 执行 SQL 查询语句: ```javascript const sql = 'SELECT * FROM 表名'; connection.query(sql, (err, results) => { if (err) { console.error('查询失败:', err); return; } console.log('查询结果:', results); }); ``` 5. 执行 SQL 插入、更新或删除语句: ```javascript const insertSql = 'INSERT INTO 表名 (列1, 列2) VALUES (?, ?)'; const insertValues = ['值1', '值2']; connection.query(insertSql, insertValues, (err, result) => { if (err) { console.error('插入失败:', err); return; } console.log('插入成功,插入的行数:', result.affectedRows); }); const updateSql = 'UPDATE 表名 SET 列1 = ? WHERE 列2 = ?'; const updateValues = ['新值', '条件值']; connection.query(updateSql, updateValues, (err, result) => { if (err) { console.error('更新失败:', err); return; } console.log('更新成功,更新的行数:', result.affectedRows); }); const deleteSql = 'DELETE FROM 表名 WHERE 列 = ?'; const deleteValues = ['条件值']; connection.query(deleteSql, deleteValues, (err, result) => { if (err) { console.error('删除失败:', err); return; } console.log('删除成功,删除的行数:', result.affectedRows); }); ``` 6. 最后,记得在完成操作后关闭数据库连接: ```javascript connection.end((err) => { if (err) { console.error('关闭数据库连接失败:', err); return; } console.log('数据库连接已关闭!'); }); ``` 这样,你就可以在 Node.js 中使用 MySQL 进行增删改查操作了。记得将上述代码中的主机名、用户名、密码、数据库名称、表名、列名、条件值等根据你的实际情况进行替换。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值