Sequelize 入门

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. 首先给关联的字段定义外键关系
1
references: {
2
	model: 关联的外键表,如User
3
	key: 关联的外键表的字段,如id
4
}
  1. 在调用hasOne或hasMany等方法的时候,通过第二个参数设置对象:{foreignKey: 当前关联表的字段,如uid}

  2. 在查询中使用 include 去设置关联的外键表模型,如:include: [MessageModel]

例:

1
// comments.js
2
'use strict';
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
'use strict';
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
});