Sequelize 是什么
Sequelize 是一个基于 promise 的 Node.js ORM, 目前支持 Postgres, MySQL, SQLite 和 Microsoft SQL Server. 它具有强大的事务支持, 关联关系, 读取和复制等功能。
ORM: 全称 Object Relational Mapping,对象关系映射,通过对象来映射和操作数据库。
安装
1 | npm i sequelize |
使用
1 | const Sequelize = require('sequelize') |
连接数据库
1 | const sequelize = new Sequelize(database: String, username: String, password: String, options: Object) |
database:数据库名称
username: 数据库用户名
password:数据库密码
options:配置选项
- host:主机,默认 localhost
- port:端口,默认 3306
- dialect:数据库类型,默认 mysql,必填
- timezone:时区,影响数据库日期时间格式的值,格式:+08:00 或 字符串格式
数据库连接也可以使用 uri
1 | postgres://user:pass@example.com:5432/dbname |
测试数据库连接
1 | sequelize.authenticate().then().catch() |
模型
模型:用来表述(描述)数据库表字段信息的对象,每一个模型对象表示数据库中的一个表,后续对数据库的操作都是通过对应的模型对象来完成的。
定义模型
1 | public define(modelName: String, attributes: Object, options: Object): Model |
modelName:模型名称,自定义
attributes:模型中包含的数据,每一个数据映射对应表中的每一个字段
options:模型(表)的设置
attributes 设置
attributes是一个对象,里面包含了对应的表中的字段信息
- key:表示字段名称
- value:字段的具体描述
字段值描述:
1 | type:字段类型,String|DataTypes |
2 | allowNull:是否允许为空,默认为true |
3 | defaultValue:默认值,默认为null |
4 | unique:值唯一,默认为false |
5 | primaryKey:是否为主键,默认为false |
6 | field:数据库中字段的实际名称 |
7 | autoIncrement:是否自增,默认false |
options 设置
timestamps:是否给每条记录添加 createdAt 和 updatedAt 字段,并在添加新数据和更新数据的时候自动设置这两个字段的值,默认为true。
paranoid:设置 deletedAt 字段,当删除一条记录的时候,并不是真的销毁记录,而是通过该字段来标示,即保留数据,进行假删除,默认为false。
freezeTableName:禁用修改表名; 默认情况下,sequelize将自动将所有传递的模型名称(define的第一个参数)转换为复数。 默认为false。
tableName:手动设置表的实际名称。
indexes:Array
1 | name:索引名称,默认模型名称+字段 |
2 | fields: Array<string>,索引字段 |
3 | unique:唯一索引,默认false |
例:
1 | const UserModel = sequelize.define('User', { |
2 | id: { |
3 | // 每一个字段的信息 |
4 | type: Sequelize.INTEGER(10), |
5 | allowNull: false, |
6 | primaryKey: true, |
7 | autoIncrement: true |
8 | }, |
9 | username: { |
10 | type: Sequelize.STRING(255), |
11 | allowNull: false, |
12 | defaultValue: '' |
13 | }, |
14 | age: { |
15 | type: Sequelize.TINYINT, |
16 | allowNull: false, |
17 | defaultValue: 0 |
18 | }, |
19 | gender: { |
20 | type: Sequelize.ENUM(['男', '女']), |
21 | allowNull: false, |
22 | defaultValue: '男' |
23 | } |
24 | }, { |
25 | // 用来设置字段以外的其他信息 |
26 | timestamps: false, |
27 | paranoid: false, |
28 | freezeTableName: true, |
29 | tableName: 'user', |
30 | indexes: [{ |
31 | name: 'uname', |
32 | fields: ['username'] |
33 | }, |
34 | { |
35 | name: 'age', |
36 | fields: ['age'] |
37 | } |
38 | ] |
39 | }); |
创建模型实例对象
一个模型类对应一个表,一个模型实例对象就是一条对应的表记录,通过操作这个对象来关联操作对应的表中的数据,操作模型类就是操作表,操作模型类对象就是操作该表中的某条记录
模型类 - 表
模型实例 - 记录
1 | public static build(options: Object): Model | Model[] |
options:一个对象,对应的就是表中的字段(模型中定义的属性),需要注意的是对该对象的操作不会立即反应到实际的数据库中,需要通过后续的操作进行同步
例:
1 | let Kimoo = UserModel.build({ |
2 | username: 'frank', |
3 | age: 18, |
4 | gender: '男' |
5 | }); |
6 | await Kimoo.save(); |
模型对象实例操作
模型对象.get(key: String):获取某个属性(字段)的值
模型对象.set(key: String, value: any):设置某个属性(字段)的值
模型对象.validate():验证模型数据
模型对象.save():验证该实例,如果通过验证,则持久化到数据库中
模型对象.update(updates: Object)
updates:要更新的字段,调用该方法等同于调用.set()然后.save()
模型对象.destroy():销毁该实例(假删除或真删除)
模型对象.findById(id: Number | String | Buffer):根据主键搜索单条记录
模型对象.findOne(options: Object):根据条件搜索一条记录
options.where:搜索条件
模型对象.findOrCreate(options: Object):搜索特定记录或创建它(如果没有对应记录)
options.where:搜索条件
模型对象.findAll(findOptions: Object):在数据库中搜索多个记录,返回数据和总计数
findOptions.where:搜索条件
findOptions.limit:记录条数限制
findOptions.offset:记录偏移
findOptions.order:记录排序方式
模型对象.findAndCountAll(findOptions: Object):在数据库中搜索多个记录,返回数据和总计数
findOptions.where:搜索条件
findOptions.limit:记录条数限制
findOptions.offset:记录偏移
findOptions.order:记录排序方式
与findAll类似,但是返回值包含 count 属性 - 返回数据与总计数
复合过滤 / OR / NOT 查询
Sequelize.Op
实例:
1 | .findOne({ |
2 | where: { |
3 | field: val, |
4 | field: {[Op.eq]: val}, |
5 | [Op.or]: [ |
6 | {field: [1,2,3]}, |
7 | {field: {[Op.gt]: 10}} |
8 | ] |
9 | } |
10 | }) |
限制,偏移,顺序和分组操作数据集
1 | .findOne({ |
2 | where:..., |
3 | limit: n, |
4 | offset: n, |
5 | order: [ [field, type], [field, type]... ], |
6 | group: [field, field,...] |
7 | }) |
统计等操作
1 | .count({ |
2 | where: {} |
3 | }) |
4 | .max(field, {where:{}}) |
5 | .min(field, {where:{}}) |
6 | .sum(field, {where: {}}) |
关联查询与预加载
1 | HasOne :model1.hasOne(model2) |
2 | HasMany :model1.hasMany(model2) |
3 | BelongsTo :model1.belongsTo(model2) |
4 | BelongsToMany :model1.belongsToMany(model2) |
5 | |
6 | model1.findOne({include[model2]}) |
- 首先给关联的字段定义外键关系
1 | references: { |
2 | model: 关联的外键表,如User |
3 | key: 关联的外键表的字段,如id |
4 | } |
在调用hasOne或hasMany等方法的时候,通过第二个参数设置对象:{foreignKey: 当前关联表的字段,如uid}
在查询中使用 include 去设置关联的外键表模型,如:include: [MessageModel]
例:
1 | // comments.js |
2 | ; |
3 | module.exports = (sequelize, DataTypes) => { |
4 | const Comments = sequelize.define('Comments', { |
5 | id: { |
6 | allowNull: false, |
7 | autoIncrement: true, |
8 | primaryKey: true, |
9 | type: DataTypes.INTEGER |
10 | }, |
11 | user_id: { |
12 | type: DataTypes.INTEGER, |
13 | allowNull: false, |
14 | references: { |
15 | model: "Users", |
16 | key: 'id' |
17 | } |
18 | }, |
19 | content: { |
20 | type: DataTypes.STRING(1000), |
21 | allowNull: false |
22 | }, |
23 | createdAt: { |
24 | allowNull: false, |
25 | type: DataTypes.DATE |
26 | }, |
27 | updatedAt: { |
28 | allowNull: false, |
29 | type: DataTypes.DATE |
30 | } |
31 | }, { |
32 | tableName: 'comments' |
33 | }); |
34 | Comments.associate = function(models) { |
35 | // associations can be defined here |
36 | Comments.belongsTo(models.Users, { |
37 | foreignKey: 'user_id' |
38 | }); |
39 | }; |
40 | return Comments; |
41 | }; |
42 | |
43 | // user.js |
44 | ; |
45 | module.exports = (sequelize, DataTypes) => { |
46 | const users = sequelize.define('Users', { |
47 | id: { |
48 | allowNull: false, |
49 | autoIncrement: true, |
50 | primaryKey: true, |
51 | type: DataTypes.INTEGER |
52 | }, |
53 | username: { |
54 | type: DataTypes.STRING(20), |
55 | allowNull: false |
56 | }, |
57 | password: { |
58 | type: DataTypes.CHAR(32), |
59 | allowNull: false |
60 | }, |
61 | createdAt: { |
62 | allowNull: false, |
63 | type: DataTypes.DATE |
64 | }, |
65 | updatedAt: { |
66 | allowNull: false, |
67 | type: DataTypes.DATE |
68 | } |
69 | }, { |
70 | tableName: 'users' |
71 | }); |
72 | users.associate = function(models) { |
73 | // associations can be defined here |
74 | users.hasMany(models.Comments, { |
75 | foreignKey: 'user_id' |
76 | }); |
77 | }; |
78 | return users; |
79 | }; |
80 | |
81 | // 查询 |
82 | Models.Contents.findAndCountAll({ |
83 | limit: 3, |
84 | offset: 0, |
85 | include: { |
86 | model: Models.Users |
87 | } |
88 | }); |