目录1.连接数据库(js/ts)2.数据库模型1.模型定义时间戳(timestamps)2.生成模型3.对应数据库操作符的定义4. 增删改查(CRUD)1. 增加Tips:对应原生s
// config.js
exports const config = {
database: {
database: 'management',
host: 'localhost',
port: 3306,
user: 'root',
passWord: '12345678'
}
}
// db.js
const Sequelize = require('sequelize');
import { config } from './config';
const { database, host, port, user, password } = config;
const sequelize = new Sequelize(database, user, password, {
dialect: 'Mysql',
host,
port,
logging: true, // logging: true, 打印sql到控制台
timezone: '+08:00', //时间上的统一,这里是东八区,默认为0时区
define: { //全局的定义,会通过连接实例传递
// timestamps: false, //默认情况下,Sequelize 使用数据类型 DataTypes.DATE 自动向每个模 型添加 createdAt 和 updatedAt 字段. 这些字段会自动进行管理 - 每当 你使用Sequelize 创建或更新内容时,这些字段都会被自动设置. createdAt 字段将包含代表创建时刻的时间戳,而 updatedAt 字段将包含 最新更新的时间戳.
//对于带有timestamps: false 参数的模型,可以禁用此行为
// createdAt: 'created_at', //自定义时间戳
// updatedAt: 'updated_at',
// paranoid: true,
// deletedAt: 'deleted_at', //paranoid表示在被告之要删除记录时并不会真正的物理上删除,而 是添加一个存有删除请求时间戳deletedAt的特殊字段。传递 paranoid: true参数给模型定义中。paranoid要求必须启用时间戳, 即必须传timestamps: true
// 把驼峰命名转换为下划线
//underscored: false,
pool: { // 使用连接池
max: 5, // 连接池中最大连接数量
min: 0, // 连接池中最小连接数量
acquire: 30000,
idle: 10000 // 如果一个线程 10 秒钟内没有被使用过的话,那么就释放线程
},
}
})
// 测试数据库链接
sequelize
.authenticate()
.then(() => {
console.log('数据库连接成功');
})
.catch((err: any) => {
// 数据库连接失败时打印输出
console.error(err);
throw err;
});
export default sequelize; // 将连接对象暴露出去
调用sequelize.define(modelName, attributes, options)
const User = sequelize.define('User', {
// 在这里定义模型属性
id: {
type: DataTypes.INTEGER,
autoIncrement: true, //允许自增
primaryKey: true
}
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING
// allowNull 默认为 true
}
}, {
// 这是其他模型参数
sequelize, // 我们需要传递连接实例
//局部的定义
modelName: 'User' // 我们需要选择模型名称
// 不要忘记启用时间戳!
timestamps: true,
// 不想要 createdAt
createdAt: false,
// 想要 updatedAt 但是希望名称叫做 updateTimestamp
updatedAt: 'updateTimestamp'
});
// `sequelize.define` 会返回模型
console.log(User === sequelize.models.User); // true
默认情况下,Sequelize 使用数据类型 DataTypes.DATE
自动向每个模型添加 createdAt
和 updatedAt
字段. 这些字段会自动进行管理 - 每当你使用Sequelize 创建或更新内容时,这些字段都会被自动设置. createdAt
字段将包含代表创建时刻的时间戳,而 updatedAt
字段将包含最新更新的时间戳.
对于带有 timestamps: false
参数的模型,可以禁用此行为,要启用createdAt,updatedAt必须要 timestamps: true
:
sequelize.define('User', {
// ... (属性)
}, {
timestamps: false
});
也可以只启用 createdAt
/updatedAt
之一,并为这些列提供自定义名称:
class Foo extends Model {}
Foo.init({ }, {
sequelize,
// 不要忘记启用时间戳!
timestamps: true,
// 不想要 createdAt
createdAt: false,
// 想要 updatedAt 但是希望名称叫做 updateTimestamp
updatedAt: 'updateTimestamp'
});
1.全局安装sequelize-auto
, mysql2
npm install -g mysql2
npm install -g sequelize-auto
2. 运行以下命令
利用sequelize-auto
对照数据库自动生成相应的models,sequelize-auto
官方文档地址:GitHub.com/sequelize/s…
//sequelize-auto -h "数据库地址" -d "数据库名" -u "用户名" -x "密码" -p "端口号" --dialect mysql
sequelize-auto -o "./model" -d test -h 127.0.0.1 -u root -p 3306 -x 123456 -e mysql
Options:
--help Show help [boolean]
--version Show version number [boolean]
-h, --host IP/Hostname for the database. [string]
-d, --database Database name. [string]
-u, --user Username for database. [string]
-x, --pass Password for database. If specified without providing
a password, it will be requested interactively from
the terminal.
-p, --port Port number for database (not for sqlite). Ex:
MySQL/MariaDB: 3306, Postgres: 5432, MSSQL: 1433
[number]
-c, --config Path to JSON file for Sequelize-Auto options and
Sequelize's constructor "options" flag object as
defined here:
https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#instance-constructor-constructor
[string]
-o, --output What directory to place the models. [string]
-e, --dialect The dialect/engine that you're using: postgres,
mysql, sqlite, mssql [string]
-a, --additional Path to JSON file containing model options (for all
tables). See the options: Https://sequelize.org/master/class/lib/model.js~Model.html#static-method- init
[string]
--indentation Number of spaces to indent [number]
-t, --tables Space-separated names of tables to import [array]
-T, --skipTables Space-separated names of tables to skip [array]
--caseModel, --cm Set case of model names: c|l|o|p|u
c = camelCase
l = lower_case
o = original (default)
p = PascalCase
u = UPPER_CASE
--caseProp, --cp Set case of property names: c|l|o|p|u
--caseFile, --cf Set case of file names: c|l|o|p|u|k
k = kebab-case
--noAlias Avoid creating alias `as` property in relations
[boolean]
--noInitModels Prevent writing the init-models file [boolean]
-n, --noWrite Prevent writing the models to disk [boolean]
-s, --schema Database schema from which to retrieve tables[string]
-v, --views Include database views in generated models [boolean]
-l, --lang Language for Model output: es5|es6|esm|ts
es5 = ES5 CJS modules (default)
es6 = ES6 CJS modules
esm = ES6 ESM modules
ts = typescript [string]
--useDefine Use `sequelize.define` instead of `init` for es6|esm|ts
--singularize, --sg Singularize model and file names from plural table
names [boolean]
const { Op } = sequelize;
[Op.and]: {a: 5} // 且 (a = 5)
[Op.or]: [{a: 5}, {a: 6}] // (a = 5 或 a = 6)
[Op.gt]: 6, // id > 6
[Op.gte]: 6, // id >= 6
[Op.lt]: 10, // id < 10
[Op.lte]: 10, // id <= 10
[Op.ne]: 20, // id != 20
[Op.eq]: 3, // = 3
[Op.not]: true, // 不是 TRUE
[Op.between]: [6, 10], // 在 6 和 10 之间
[Op.notBetween]: [11, 15], // 不在 11 和 15 之间
[Op.in]: [1, 2], // 在 [1, 2] 之中
[Op.notIn]: [1, 2], // 不在 [1, 2] 之中
[Op.like]: '%hat', // 包含 '%hat'
[Op.notLike]: '%hat' // 不包含 '%hat'
[Op.iLike]: '%hat' // 包含 '%hat' (不区分大小写) (仅限 PG)
[Op.notILike]: '%hat' // 不包含 '%hat' (仅限 PG)
[Op.regexp]: '^[h|a|t]' // 匹配正则表达式/~ '^[h|a|t]' (仅限 MySQL/PG)
[Op.notRegexp]: '^[h|a|t]' // 不匹配正则表达式/!~ '^[h|a|t]' (仅限 MySQL/PG)
[Op.iRegexp]: '^[h|a|t]' // ~* '^[h|a|t]' (仅限 PG)
[Op.notIRegexp]: '^[h|a|t]' // !~* '^[h|a|t]' (仅限 PG)
[Op.like]: { [Op.any]: ['cat', 'hat']} // 包含任何数组['cat', 'hat'] - 同样适用于 iLike 和 notLike
[Op.overlap]: [1, 2] // && [1, 2] (PG数组重叠运算符)
[Op.contains]: [1, 2] // @> [1, 2] (PG数组包含运算符)
[Op.contained]: [1, 2] // <@ [1, 2] (PG数组包含于运算符)
[Op.any]: [2,3] // 任何数组[2, 3]::INTEGER (仅限PG)
[Op.col]: 'user.organization_id' // = 'user'.'organization_id', 使用数据库语言特定的列标识符, 本例使用
$and: {a: 5} // AND (a = 5)
$or: [{a: 5}, {a: 6}] // (a = 5 OR a = 6)
$gt: 6, // > 6
$gte: 6, // >= 6
$lt: 10, // < 10
$lte: 10, // <= 10
$ne: 20, // != 20
$not: true, // IS NOT TRUE
$between: [6, 10], // BETWEEN 6 AND 10
$notBetween: [11, 15], // NOT BETWEEN 11 AND 15
$in: [1, 2], // IN [1, 2]
$notIn: [1, 2], // NOT IN [1, 2]
$like: '%hat', // LIKE '%hat'
$notLike: '%hat' // NOT LIKE '%hat'
$iLike: '%hat' // ILIKE '%hat' (case insensitive) (PG only)
$notILike: '%hat' // NOT ILIKE '%hat' (PG only)
$like: { $any: ['cat', 'hat']}
// LIKE ANY ARRAY['cat', 'hat'] - also works for iLike and notLike
$overlap: [1, 2] // && [1, 2] (PG array overlap operator)
$contains: [1, 2] // @> [1, 2] (PG array contains operator)
$contained: [1, 2] // <@ [1, 2] (PG array contained by operator)
$any: [2,3] // ANY ARRAY[2, 3]::INTEGER (PG only)
$col: 'user.organization_id' // = "user"."organization_id", with dialect specific column identifiers, PG in this example
//or操作符的两种使用 order_status=0 or order_status=1
params['$or'] = [{ order_status: 0 }, { order_status: 1 }];
params['order_status'] = {
$or: [
{ $eq: 0 },
{ $eq: 1 }
]
}
create
向数据库中添加单条记录。
const User = sequelize.import('./model/user'); //导入模型
const user = await User.create({
username: 'alice123',
isAdmin: true
});
bulkCreate
批量创建,通过接收数组对象而不是单个对象。
await User.bulkCreate([
{ username: 'foo', pwd:"123"},
{ username: 'bar', pwd:"345"}
], { updateOnDuplicate: true, fields: ['username','pwd','address'] });
updateOnDuplicate
: 如果行键已存在是否更新。数据库表中现有的记录的唯一索引或者主键如果已经存在,执行更新操作(true表示更新,false表示不更新。 默认为更新)
fields
: 要定义字段的数组(其余字段将被忽略),用来限制实际插入的列。
在MySQL数据库中,如果在insert语句后面带上ON DUPLICATE KEY UPDATE 子句。
除非找到一个满足查询参数的结果,否则方法 findOrCreate
将在表中创建一个条目. 在这两种情况下,它将返回一个实例(找到的实例或创建的实例)和一个布尔值,指示该实例是已创建还是已经存在.
使用 where
参数来查找条目,而使用 defaults
参数来定义必须创建的内容. 如果 defaults
不包含每一列的值,则 Sequelize 将采用 where
的值(如果存在).
const [user, created] = await User.findOrCreate({
where: { username: '123' },
defaults: {
job: 'Technical Lead javascript'
}
});
console.log(user.username); // 'sdepold'
console.log(user.job); // 这可能是也可能不是 'Technical Lead JavaScript'
console.log(created); // 指示此实例是否刚刚创建的布尔值
if (created) {
console.log(user.job); // 这里肯定是 'Technical Lead JavaScript'
}
const result = await Goods.findAll({
attributes: [
'goodsId',
[sequelize.fn('SUM', sequelize.col('order_count')), 'order_count'],
[sequelize.fn('SUM', sequelize.col('total_price_sum')), 'total_price_sum'],
[sequelize.fn('SUM', sequelize.col('goods_cost')), 'goods_cost'],
[sequelize.fn('COUNT', sequelize.col('goodsId')), 'goods_count']
],
where: params,
limit: 10,
offset:0,
raw: true,
group: [sequelize.col('goodsId')],
})
1. attributes
如果只需要查询模型的部分属性,可以在通过在查询选项中指定attributes
实现,如[colName1,colName2,colName3......]
。
当需要查询所有字段并对某一字段使用聚合查询时,而只需要以对象的形式传入attributes
并添加include
子属性即可。
// 指定全查询字段比较麻烦
Model.findAll({
attributes: ['id', 'foo', 'bar', 'baz', 'quz', [sequelize.fn('COUNT', sequelize.col('hats')), 'hats_count']]
});
// 这样会比较简短,且在你添加/删除属性后不会出错
Model.findAll({
attributes: { include: [[sequelize.fn('COUNT', sequelize.col('hats')), 'hats_count']] }
});
全部查询时,可以通过exclude
子属性来排除不需要查询的字段:
Model.findAll({
attributes: { exclude: ['baz'] }
});
为列取一个别名:
在attributes
数组里面添加一项 [ oldColName , newColName ]
或者 [ sequelize.col('oldColName') , newColName ]
通过sequelize.fn方法可以进行聚合查询:
如常用的SUM
,COUNT
等。
2. where
在模型的 findOne
/finAll
或 update
/destroy
操作中,可以指定一个where
选项以指定筛选条件,where
是一个包含属性/值对对象,sequelize会根据此对象生产查询语句的筛选条件。
where:{ //查询 username='admin' pwd ='123456' user_status=0 or user_status=1
username: 'admin',
pwd:"123456",
user_status:{
[Op.or]: [
{ $eq: 0 },
{ $eq: 1 }
]
}
}
可以配合符操作来做复杂的筛选条件。
3. limit
,offset
查询进,我们可以使用limit
限制返回结果条数,并可以通过offset
来设置查询偏移(跳过)量,通过这两个属性我们可以实现分页查询的功能:
Model.findAll({ limit: 10 }) // 获取 10 条数据(实例)
Model.findAll({ offset: 8 }) // 跳过 8 条数据(实例)
Model.findAll({ offset: 5, limit: 5 }) // 跳过 5 条数据并获取其后的 5 条数据(实例)
//使用场景,分页请求数据
const page = parseInt(params.page || 1);
const limit = parseInt(params.limit || 10);
const currentPage = (page - 1) * limit;
Model.findAll({
limit,
offset: currentPage,
})
4. raw
{ raw: true }
作为参数传递给 finder时,可以对查询的结果集禁用包装。
5. order
order
参数采用一系列 项 来让 sequelize 方法对查询进行排序. 这些 项 本身是 [column, direction]
形式的数组. 该列将被正确转义,并且将在有效方向列表中进行验证(例如 ASC
, DESC
, NULLS FIRST
等).
Model.findAll({
order: [
//sequelize.col('date') 有时候可以使用sequelize.col()指定列,防止在子查询或者关联查询时找不到列名
[sequelize.col('date'), 'DESC'],
['date', 'DESC'],
// 将转义 title 并针对有效方向列表进行降序排列
['title', 'DESC'],
// 将按最大年龄进行升序排序
sequelize.fn('max', sequelize.col('age')),
// 将按最大年龄进行降序排序
[sequelize.fn('max', sequelize.col('age')), 'DESC'],
// 将按 otherfunction(`col1`, 12, 'lalala') 进行降序排序
[sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],
// 将使用模型名称作为关联名称按关联模型的 createdAt 排序.
[Task, 'createdAt', 'DESC'],
// 将使用模型名称作为关联名称通过关联模型的 createdAt 排序.
[Task, Project, 'createdAt', 'DESC'],
// 将使用关联名称按关联模型的 createdAt 排序.
['Task', 'createdAt', 'DESC'],
// 将使用关联的名称按嵌套的关联模型的 createdAt 排序.
['Task', 'Project', 'createdAt', 'DESC'],
// 将使用关联对象按关联模型的 createdAt 排序. (首选方法)
[Subtask.associations.Task, 'createdAt', 'DESC'],
// 将使用关联对象按嵌套关联模型的 createdAt 排序. (首选方法)
[Subtask.associations.Task, Task.associations.Project, 'createdAt', 'DESC'],
// 将使用简单的关联对象按关联模型的 createdAt 排序.
[{model: Task, as: 'Task'}, 'createdAt', 'DESC'],
// 将由嵌套关联模型的 createdAt 简单关联对象排序.
[{model: Task, as: 'Task'}, {model: Project, as: 'Project'}, 'createdAt', 'DESC']
],
// 将按最大年龄降序排列
order: sequelize.literal('max(age) DESC'),
// 如果忽略方向,则默认升序,将按最大年龄升序排序
order: sequelize.fn('max', sequelize.col('age')),
// 如果省略方向,则默认升序, 将按年龄升序排列
order: sequelize.col('age'),
// 将根据方言随机排序(但不是 fn('RAND') 或 fn('RANDOM'))
order: sequelize.random()
});
Model.findOne({
order: [
// 将返回 `name`
['name'],
// 将返回 `username` DESC
['username', 'DESC'],
// 将返回 max(`age`)
sequelize.fn('max', sequelize.col('age')),
// 将返回 max(`age`) DESC
[sequelize.fn('max', sequelize.col('age')), 'DESC'],
// 将返回 otherfunction(`col1`, 12, 'lalala') DESC
[sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],
// 将返回 otherfunction(awesomefunction(`col`)) DESC, 这种嵌套可能是无限的!
[sequelize.fn('otherfunction', sequelize.fn('awesomefunction', sequelize.col('col'))), 'DESC']
]
});
order
数组的元素可以如下:
一个字符串 (它将被自动引用)
一个数组, 其第一个元素将被引用,第二个将被逐字追加
一个具有raw
字段的对象:
raw
内容将不加引用地逐字添加raw
,查询将失败调用 Sequelize.fn
(这将在 SQL 中生成一个函数调用)
调用 Sequelize.col
(这将引用列名)
6. group
分组和排序的语法相同,只是分组不接受方向作为数组的最后一个参数(不存在 ASC
, DESC
, NULLS FIRST
等).
还可以将字符串直接传递给 group
,该字符串将直接(普通)包含在生成的 SQL 中.
Model.findAll({ group: 'name' });
Model.findAll({
group: [sequelize.col('date'),sequelize.col('id')] //可以指定多个列进行分组
});
// 生成 'GROUP BY name'
Tips:在做分组和排序的时候可以使用sequelize.col()指定列,防止在子查询或者关联查询时找不到列名
7. include
include
关键字表示关联查询
1. findOne
findOne
方法获得它找到的第一个条目(它可以满足提供的可选查询参数).
const user = await User.findOne({ where: { username: 'admin' } });
2.findAll
该查询将从表中检索所有条目(除非受到 where
子句的限制).
const user = await User.findAll({ where: { username: 'admin' },raw:true });
3.findAndCountAll,findAndCount
findAndCountAll
方法是结合了 findAll
和 count
的便捷方法. 在处理与分页有关的查询时非常有用,在分页中,你想检索带有 limit
和 offset
的数据,但又需要知道与查询匹配的记录总数.
当没有提供 group
时, findAndCountAll
方法返回一个具有两个属性的对象:
count
: 一个整数 - 与查询匹配的记录总数rows
:一个数组对象 - 获得的记录当提供了 group
时, findAndCountAll
方法返回一个具有两个属性的对象:
count
- 一个数组对象 - 包含每组中的合计和预设属性rows
- 一个数组对象 - 获得的记录 const { count, rows } = await User.findAndCountAll({
where: {
username: {
[Op.like]: '%foo%'
}
},
offset: 10, //查询偏移(跳过)量
limit: 2 //限制返回结果条数
});
let result = await Goods.findAndCount({
include: [
{
attributes: [[sequelize.col('title'), 'goods_name']],
association: Goods.belongsTo(tbGoods, { targeTKEy: 'goodsId', foreignKey: 'goodsId' , as:'goods_name_info'}),
model: Goods,
required: false,
where: params2,
}
],
where: params,
limit,
offset: currentPage,
raw: true,
order: [
[sequelize.col('date'), 'DESC'],
]
})
A.hasOne(B, { }); // A 有一个 B
A.belongsTo(B, { }); // A 属于 B
A.hasMany(B, { }); // A 有多个 B
A.belongsToMany(B, { through: 'C', }); // A 属于多个 B , 通过联结表 C
association
as
指定连接的别名
where
关联中也支持where子句。
required
false,表示左外连接(LEFT OUTER JOIN),左表全部出现在结果集中,若右表无对应记录,则相应字段为NULL
。
true,表示内连接(INNER JOIN),满足条件的记录才会出现在结果集中。
Tips:由于 sequelize.literal
会插入任意内容而不进行转义
//根据goodsId 去匹配 goods_order对应的 goods_name
let result = await goods_roi.findAll({
attributes: [
'goodsId',
[sequelize.fn('SUM', sequelize.col('order_count')), 'order_count'],
[sequelize.fn('SUM', sequelize.col('total_price_sum')), 'total_price_sum'],
[sequelize.fn('SUM', sequelize.col('goods_cost')), 'goods_cost'],
[
sequelize.literal(`(
SELECT item_title
FROM goods_order AS goods_order
WHERE
goods_order.item_id = goods_roi.goodsId limit 1
)`),
'goods_name'
]
],
where: params,
raw: true,
group: [sequelize.col('goodsId')]
})
实用方法 count
,max
,min
,sum
,increment
, decrement
count
方法仅计算数据库中元素出现的次数
const amount = await Model.count({
where: {
id: {
[Op.gt]: 25
}
}
});
console.log(`这有 ${amount} 个记录 id 大于 25`);
max
, min
和 sum
假设我们有三个用户,分别是10、5和40岁
await User.max('age'); // 40
await User.max('age', { where: { age: { [Op.lt]: 20 } } }); // 10
await User.min('age'); // 5
await User.min('age', { where: { age: { [Op.gt]: 5 } } }); // 10
await User.sum('age'); // 55
await User.sum('age', { where: { age: { [Op.gt]: 5 } } }); // 50
increment自增, decrement自减
await User.increment({age: 5}, { where: { id: 1 } }) // 将年龄增加到15岁
await User.increment({age: -5}, { where: { id: 1 } }) // 将年龄降至5岁
update查询也接受 where
参数
*// 将所有没有姓氏的人更改为 "Doe"*
await User.update({ lastName: "Doe" }, {
where: {
lastName: null
}
});
destroy查询也接受 where
参数
*// 删除所有名为 "Jane" 的人*
await User.destroy({
where: {
firstName: "Jane"
}
});
Sequelize 支持两种使用事务的方式:
托管事务会自动处理提交或回滚事务. 通过将回调传递给 sequelize.transaction
来启动托管事务. 这个回调可以是 async
(通常是)的.
在这种情况下,将发生以下情况:
t
t
只有这样,sequelize.transaction
调用才会解决:
try {
const result = await sequelize.transaction(async (t) => {
const user = await User.create({
firstName: 'Abraham',
lastName: 'Lincoln'
}, { transaction: t }); //{transaction: t} 必须作为第二个对象里的参数传递
return user;
});
// 如果执行到此行,则表示事务已成功提交,`result`是事务返回的结果
// `result` 就是从事务回调中返回的结果(在这种情况下为 `user`)
} catch (error) {
// 如果执行到此,则发生错误.
// 该事务已由 Sequelize 自动回滚!
}
注意:t.commit()
和 t.rollback()
没有被直接调用.
自动将事务传递给所有查询:在上面的示例中,仍然通过传递 { transaction: t }
作为第二个参数来手动传递事务.
以上为js版本,部分不适用于ts,ts要根据具体的官方文档使用。
以上就是nodejs Sequelize手册学习快速入门到应用的详细内容,更多关于nodejs Sequelize入门手册的资料请关注编程网其它相关文章!
--结束END--
本文标题: Nodejs Sequelize手册学习快速入门到应用
本文链接: https://lsjlt.com/news/170354.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-12
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0