- 基础使用
- 初始化
new Sequlize({}) 配置
{ define } 及是 Model.init 配置。define 只能定义 Model.init 里 options 的相关内容
- 默认会给模型添加
id/createdAt/updatedAt等字段,可以更改
- 其他方法
- 原始查询
const [results, metadata] = sequelize.query(mysql)
- sequelize.fn(fn, args) 用于创建数据库函数对象。在
where/order中使用
- sequelize.col(string) 创建数据库列对象。建议使用
table.colum 完整命名方式
attributes: {[Sequelize.fn('DISTINCT', Sequelize.col('external_info.status_code')), 'statusCode']}
[Sequelize.fn('count', Sequelize.col('id')), 'num']
- 注:可配合
npm i -g sequelize-auto 自动获取已有表生成对应的 model
new Sequelize({
define: {
charset: 'utf8mb4',
collate: 'utf8mb4_general_ci',
createdAt: 'createTime',
updatedAt: 'updateTime',
deleteAt: 'deleteTime',
underscored: true,
freezeTableName: true
}
});
{ type, allowNull: true, defautlValue, unique, primaryKey, autoIncrement, comment, field, validate }
sequlize.define('modelName', { column_field }, { paranoid });
const { Model } = require('sequlize');
const sequelize = new Sequelize('sqlite::memory');
class User extends Model {
getFullName() {
return [this.firstname, this.lastname].join(' ');
}
}
User.init({ column_field }, {
sequelize,
tableName: 'xxx_xxx'
})
- 数据类型
- TEXT(length)
- STRING(length)
- CHAR(length)
- NUMBER(options)
- optons
- .length/.zerofill/.unsigned/.decimals/.precision/.scale
- TINYINT(options)
- INTEGER(options)
- BIGINT(options)
- FLOAT(length, decimals)
- DOUBLE(length, decimals)
- DECIMAL(precision, scale)
- BOOLEAN 便捷 TINYINT(1)
- DATE(length): Date column with timezone, default is UTC
- DATEONLY: A date only column (no timestamp)
- NOW: A default value of the current timestamp
- BLOB(length)
-虚拟字段、get/set
- .define(ModelName, { columns }) 时可设置 **get **并调用
this.getDataValue( columnName )
- 本字段 getter 内不能直接使用
this.本字段名 方式获取值,它会造成 Sequelize 无限循环。非本字段的可以使用。
- 设置 set( value ) 并调用
this.setDataValue( columnName, value )
- 虚拟字段:定义 table 并不存在的列,类似 vue-computed
- 需要配合
DataTypes.VIRTUAL 特殊字段使用,告诉模型并没有实际的列
- 然后配置 get 获取内容,set 作为设置值
password: {
type: DataTypes.STRING,
allowNull: false
get() {
const rawValue = this.getDataValue('password');
return `**${rawValue}**`;
},
set(value) {
this.setDataValue('password', doCrypto(value));
}
},
- Model.api
- insert
- build({}) 它不连接数据库,只是创建一个本地对象(非异步)。需要调用 x.save() 真正保存
- create({values}, {options}) 返回插入的数据对象;可通过
res.xxx获取内容
- 返回的实例包含一下方法
- .toJSON()
- .save/save( [{ fields: ['xxx'] }] ) 可仅保存选择的内容
- 执行时会把所有更改同步到数据库。如:
xxx.name='';xxx.set({});
- .destroy()
- .reload() 未调用
.save()时可获取原数据
- .increment/decrement({ key: value })
- 它是
x.build/save()的组合操作
- bulkCreate([{values}], {options}) _批量。_返回插入的数据对象数组;可通过
res[0].xxx获取内容
- delete
- destroy({options}) 返回执行结果数,没有返回
0;
- { truncate: true } 删除该表所有内容
- update
- update({values}, {options}) 返回结果数组,没有返回
[0];
- 执行后数据直接同步数据库,不需要再调用
save()
- select
- findAll({options}) 返回结果对象数组,没有返回
[];可通过 rows[0].xxx获取内容
- findByPk(number | string, {options}) 返回结果对象,没有返回
null;可通过 row.xxx获取内容
- findOne({options}) LIMIT 1 返回结果对象,没有返回
null;可通过 row.xxx获取内容
- findAndCountAll({options}) 返回**结果集 **
{count, rows};可通过 rows[0].xxx获取内容
- other
- count({options}) 返回结果数 6
- max/min/sum(string, {options}) 返回结果数 5
- drop({options}) 删除表
- 其他 rowInstance 内容
- 通过查询/创建等方式获取的
row其实并不是直接的数据对象,而是rowInstance里面挂载这很多sequelize提供的方法
- 通过
row.columnName/.get('key')获取单列数据内容
- 通过
row.columnName='xxx'/.set('key','value'|{ object })更改数据。非直接同步需要执行save()
- 通过
row.update({})为实时同步数据库更新
row.changed()返回[...'columnName']数据更改的列名或false说明数据未更改。
- 注意
row.columnName/.set()更改得值和原始值相同返回的是false
row.previous()返回{key:value}更改数据所对应的原数据内容
row.isNewRecord返回boolean说明该记录是否为数据库内真实数据。像xx.build()创建的数据就非真实数据
row.get({ plain: true })/toJSON()都返回真实数据对象。
- 注意
findAll()返回的数组,所以要在数组项上才能调用
- 获取的
rowInstance 是可以进行链式操作的;如:const row = xxx.findByPk() -> row.update/save/destroy({a: 123}) 返回的还是 row
- 查询条件 options
- 默认下所有的列名都已经是 aaBb 命名方式了可直接使用
- options.attributes
- 如果需要 alias 是要使用真列名和更改的名称
['file_name', 'fName']
- 注:使用
as别名后不能直接res.xxx要用res.get('xxx')获取
.include/.exclude 在默认获取全部字段下,再次对数据进行处理
- 操作符 Op
- 基本语法
{ where: { id: { [Op.gte]: 10 } } }
- 所有属性之间是通过 AND 连接
- 可以在创建 sequelize 实例时,添加 _operatorsAliases _属性给对应操作符添加别名
- Op.eq / ~.ne 表示 = / !=
- ~.is / ~.not 表示 IS xxx / IS NOT xxx
- ~.and / ~.or 事例:[Op.or]: [{ code: code }, { name: name }]
- ~.gt / ~.gte 表示 > / >=
- ~.lt / ~.lte 表示 > / <=
- ~.between / ~.notBetween 表示 BETWEEN x AND x / NOT BETWEEN x AND x
- ~.in / ~.notIn 表示 IN [1, 2] / NOT IN [1, 2]
- ~.like / ~.notLike / ~.startsWith / ~.endsWith / ~.substrng
- 注意: 不能传递 undefined。null(会转为 IS NULL) 和 '' 要去看情况使用。
- options.order: [['name', 'DESC']]
- options.offset 偏移量
- options.limit 限制条数
- options.group 分组
- options.raw = true 返回源数据;有关联的返回的是 'domain.id': 'xxx'
- options.include 关联表
- 支持 Model | string | array;string 时为实际的表名 domain_info
- ~.model / ~.as 使用对象方式引入别名时,这两个属性都要写
- ~.association 可不使用 model
- ~.where / ~.attributes
- 配置 where 属性后会强制改为
INNER JOIN 连接,可通过设置 required: false 更改
- 为了获取
顶层的 WHERE 可使用$nested.columRealName$语法,支持多级嵌套
- 注: where 内的条件都是子连接内进行的是 AND 的关联。
- ~.required: false(默认) 为 LEFT OUTER JOIN 模式,设置 true 转为 INNER JOIN
- ~.or: false 使用 OR 替换 AND
- ~.right: false 使用 RIGHT JOIN 连接
- ~.limit
- 偏执表(删除)
- 创建表时设置
{ paranoid: true } 后记录将不会真正删除,而是用deletedAt列数据代替
- 数据恢复使用
xx.restore()函数即可
- 如果还需要强制删除,在执行
xx.destory({ force: true }) 配置强制参数
- 其他查询时默认是不查询软删除的数据,可通过配置
findAll({ paranoid:false })查询
- 关联查询
A.hasOne(B, { });
A.belongsTo(B, { });
A.hasMany(B, { });
A.belongsToMany(B, { through: 'C', });
- 关联表之间定义顺序对结果是有影响的。在上述所有示例中
A称为源模型,而B称为目标模型。一个源可对应一个/多个目标,但一个目标只能对一个源。
- _foreignKey _外键及可在
hasOne/hasMany 中,也可在 belongsTo 中定义。并且也支持对象形式可指定如:type、allowNull、defaultValue 等参数
- 一对一:
hasOne和belongsTo关联一起使用;
- 一对多:
hasMany和belongsTo关联一起使用;
A.hasMany(B, {sourceKey, foreignKey})
A中的记录一个对多个B中的,外键在B
- 创建非主键字段的关联:_sourceKey _用于定义
B中 foreignkey 外键,所对应A中的实际字段名
B.belongsTo(A, {targetKey, foreignKey})
B中有记录值属于A,外键在B
- 创建非主键字段的关联:_targetKey _用于定义
B中 _foreignKey _外键,所对应A中的实际字段名
- 使用非主键字段的关联 hasMany/belongsTo 都需要写上 sourceKey/targetKey/_foreignKey _并为一个值。要不然 sequelize 还是会按照自己的方式拿而外的外键去查询
- 多对多(常用与中间表):两个
belongsToMany(, {through})调用一起使用;
{ through: 'xx' }为关联的中间表**(必填项)**
- 注意:实际关联表并不需要在
include:{}内出现,它只是起到中间关联的作用
- options:
{ sourceKey, targetKey, foreignKey, as }
- as 别名:当一个模型需要定义两个不同的关联时使用。as 可直接代替 foreignKey ,也可同时使用。
- 定义后在 include 时只能使用别名 as。
- hasOne/hasMany/belongsTo 中都可定义 as,但在 hasMany 中设置 as 返回的是 []
- 一般定义在 belongsTo 中
- 延迟加载/预先加载
- 延迟:指等用到了,再获取关联数据
- 预先(include):开始查询事,直接一次获取相关关联数据
- 注:关联查询出的数据是个单独的对象;
- 注:默认是
outer join/ left join 方式
- 实例关联后添加的特殊方法
- 一对一的
instance.createModelB({ 数据对象 })
getModelB/setModelB( id/instance )
- 一对多、多对多
instance.createModelB({ 数据对象 })
hasModelB/addModelB/removeModelB( id/instance )
instance.getModelBs/countModelBs/hasModelBs/addModelBs/removeModelBs/setModelBs([ id/instance ])都是复数形式
- addModelBs/removeModelBs 是把关联表中已有数据和目标
row做关联
- 重要内容
.getXXX/countXXXs/hasXXXs()接受参数,可想findAll({ where: {} })类似的
- 添加/删除方式不建议使用
.setMBs(null|[2,3])。因为它只会关联id=[2,3]的记录并把该pId的其他记录关联清除。所以不清楚情况下老实用.addXXXs/removeXXXs()
- 多对多使用
.addXXX/removeXXX(rowC)会自动往中间表新增/删除两者之间的关联记录,不用手动在插入
- 多对多
.addXXX()时不太建议使用[id]方式。因为并不会判断c表中实际有无该id就进行插入,所以更建议使用[instance]方式
- 多对多时如果中间表除了关联的外键外,还有其他的字段可能就不太合适用上面的方式了。因为没办法给它们传递内容
- 要么就在中间表上多做个
a.hasMany(c)关联,使用时a/b表手动创建。然后a.createC({ bId, 其他参数 })做中间表关联
- 事务
- 非全局自动添加时,所有需要进入事务的都需要添加
{ transaction: t }配置
- 非托管事务
- 创建事务并配置,然后手动执行
t.commit/rollback()进操作
- 托管事务
- 所有
增/删/改/查以及对应的关联表操作都可配置事务,只要其中一个出错全部都回滚
- 可通过手动抛错
throw new Error()强制回滚
- 全局自动事务:配合
cls-hooked 库使用。配置Sequelize.useCLS(cls.createNamespace('_xxx_'))
- 多个事务嵌套是默认取最近的那个事务,也可
{ transaction: t1 }手动选择配置
- 配置
{ transaction: null }可跳过事务处理
- Model 同步
- Model.sync() 如果表不存在,则创建该表(如果已经存在,则不执行任何操作)
- force: true 将创建表。如果表已经存在,则将其首先删除
- alter: boolean/object 这将检查数据库中表的当前状态(它具有哪些列,它们的数据类型等),然后在表中进行必要的更改以使其与模型匹配
- alter.drop: false 防止对表内不同的内容,禁止执行任何 drop
- match: /RegExp/ 只对匹配到的表名进行处理