1. hello world
  2. 创建表
  3. 新增数据
    1. create
    2. bulkCreate
    3. findOrCreate
  4. 修改数据
    1. update
    2. upsert
  5. 查询数据
    1. findAll
    2. findAndCountAll
    3. findByPk
    4. findOne
    5. count
  6. 删除数据
    1. destroy
  7. Model
  8. option 参数
    1. where
    2. order
  9. 参考

Sequelize

Sequelize 是基于 Node 的 ORM 库, 支持的数据库有 Postgres | MySQL | MariaDB, SQLite | Microsoft SQL Server.
Sequelize 将数据库键值对映射成对象, 将增删改查操作映射成方法,抹平了不同数据库间的语法区别.

hello world

安装 Sequelize

1
2
yarn add sequelize
yarn add sqlite3

hello world

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const Sequelize = require("sequelize");

// 创建数据库连接
const db = new Sequelize({
dialect: "sqlite",
storage: "./db.sqlite",
});

// 创建表
const userTable = db.define("user", {
name: Sequelize.STRING,
age: {
// data type
type: Sequelize.INTEGER,
// 默认值
defaultValue: 18,
},
});

(async () => {
// 同步数据库
await db.sync();
// 写入内容
await userTable.create({
name: "anna",
});

// 关闭数据库
db.close();
})();

创建表

Sequelize 会自动添加 createdAt 和 updatedAt, 分别对应创建时间和更新时间.可通过设置 timestamps: false 禁止自动添加 createdAt 和 updatedAt.

1
db.define("user", {}, { timestamps: false });

新增数据

create

新增数据, 创建一个 model 并调用 save. Model | Sequelize

1
2
3
4
5
const anna = await userTable.create({
name: "anna",
age: 20,
});
console.log(anna.name, anna.age);

可通过修改这个返回的 model 来更新表中所对应的数据

1
2
anna.age = 25;
await anna.save(); // 调用 save 方法来同步修改

bulkCreate

批量新增, 返回一个数组,包含一组表示映射关系的 model. Model | Sequelize

1
2
3
4
5
const user = [{ name: "anna", age: 20 }, { name: "bob", age: 25 }];
const userList = await userTable.bulkCreate(user);
for (let i of result) {
console.log(i.userList); // anna bob;
}

findOrCreate

没有找到对应值则新增,有则不不做任何更改.
返回一个数组, 其中包含一个表示映射关系的 model,和一个表示是否是新增数据的布尔值.

查找 name: "anna" 是否存在, 不存在时用 defaults 参数中的值新建.

1
2
3
4
5
6
7
8
const [anna, isCreate] = await userTable.findOrCreate({
defaults: {
name: "david",
age: 20,
},
where: { name: "david" },
});
console.log(anna.name, isCreate); // david true

修改数据

update

更新数据, 必须提供属性 where. Model | Sequelize
返回一个数组,包含两个数值.第一个数值为修改行数, 第二个值为实际影响的行数(? 仅支持 postgres )

1
2
3
4
5
const updateInfo = await userTable.update(
{ name: "ava", age: 22 },
{ where: { name: "anna" } } // 将 name 值 anna 更改为 ava
);
console.log(updateInfo); // [ 1 ]

upsert

符合条件则修改该行数据, 未找到则新增一行数据. Model | Sequelize
返回一个布尔值, 表示该操作是新增还是修改.(不同数据库的返回值各不相同, sqlite 不返回任何值, 详见官方文档).

upsert 只根据参数的 主键/设置了唯一标识( unique: true) 来判断是否更新某行, 不支持 where.

务必要保证提供了 主键(例如 id)/设置了唯一标识的参数

1
2
3
4
5
6
7
8
9
10
await userTable.upsert({ name: "liam", age: 25, id: 1 });
// or
const userTable = db.define("user", {
name: {
type: Sequelize.STRING,
unique: true, // 唯一标识
},
});
await db.sync({}); // 注意: 不要使用 alter: true, 这个参数不会同步 unique 标识. (尚不知这是否是 bug)
await userTable.upsert({ name: "liam", age: 25 });

错误示例, 只会插入一行新数据:

1
2
3
4
5
6
const liam = userTable.build({
name: "liam",
age: 20,
});
await liam.save();
await userTable.upsert({ name: "liam", age: 25 }, { where: { name: "liam" } });

捕获.PNG

查询数据

findAll

获取多行数据,可用 where 参数设置查询条件.
返回一个数组, 包含匹配到的 model.未找到到时返回空数组.

返回所有数据:

1
2
3
4
const findList = await userTable.findAll();
for (let i of findList) {
console.log(i.name); anna ava liam
}

使用 where 设置过滤条件:

1
2
3
4
5
6
7
const findList = await userTable.findAll({
where: { name: "anna" },
});
for (let i of findList) {
console.log(i.name);
anna;
}

可通过 limit 设置返回的行数
只返回一条记录:

1
const findList = await userTable.findAll({ limit: 1 });

设置排序,其中的 ASC 表示升序, DESC 表示降序
按 name 降序排列. 如果 name 值相同, 则相同值按 age 升序排列:

1
2
3
const findList = await userTable.findAll({
order: [["name", "DESC"], ["age", "ASC"]],
});

设置偏移量(起始位置):

1
await userTable.findAll({ offset: 2 });

findAndCountAll

类似 findAll, 同样支持 where offset limit order 等参数.

区别为除了返回匹配到的数据之外,还返回所匹配的行数.
其返回一个对象, 其包含两个属性: count 和 rows.
count 为匹配数据的总数, 受 where 影响, 但不受 offset limit 影响.
rows 为匹配到的数据(即 findAll 的返回值).

1
2
3
4
5
6
7
8
9
10
let findInfo = await userTable.findAndCountAll();
console.log(findInfo.count); // 5

// 使用 where 后, count 减少
findInfo = await userTable.findAndCountAll({ where: { name: "ava" } });
console.log(findInfo.count); // 1

// 不受 limit 影响,仍然返回了所匹配数据的总数
findInfo = await userTable.findAndCountAll({ limit: 1 });
console.log(findInfo.count); // 1

通过 limit offset 实现分页功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
* currentPage 当前页码, 从 1 开始
* pageSize 每页展示数量
* return {
* count, 总数
* rows 表数据
* }
*/
async function pagation(currentPage, pageSize) {
return await userTable.findAndCountAll({
offset: (currentPage - 1) * pageSize,
limit: pageSize,
});
}
// 获取第 2 页的数据, 每页 3 个
const result = await pagation(2, 3);
console.log(result.count);
for (let i of result.rows) {
console.log(i.name);
}

findByPk

通过主键获取数据, 未找到时返回 null.

1
2
const model = await userTable.findByPk(1);
console.log(model.name); // anna

findOne

返回找到的第一个 model,相当于 findAll({limit: 1}).
未找到时返回 null.

1
2
const model = await userTable.findOne();
console.log(model.name); // anna
1
2
3
4
const model = await userTable.findOne({
where: { name: "ava" },
});
console.log(model.name); // ava

count

返回匹配的记录行数

1
2
const count = await userTable.count();
console.log(count); // 10

使用 where 参数过滤匹配条件

1
2
3
4
const count = await userTable.count({
where: { name: "anna" },
});
console.log(count); // 1

删除数据

destroy

删除匹配的记录, 必须提供 where 参数.
返回一个数值,表示删了几行.

1
2
3
4
const count = await userTable.destroy({
where: { name: "anna" },
});
console.log(count); // 1

Model

Model 实例是对表行的映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 创建 model
const liam = userTable.build({
name: "liam",
age: 20,
});

// 调用 save 将操作同步到数据库中
await liam.save();

// 修改 model
liam.age = 30;

// 删除 model
await liam.destroy();

await liam.save();

对于某些类型(例如 Sequelize.JSON), 只调用 model.save 可能不起作用.
需要在 调用 save 方法前 调用 changed(key name, true) 方法.

1
2
3
4
model.changed("value", true);
// or
// model.set('value', this.settingModel.value);
await model.save();

option 参数

where

sequelize-docs-Zh-CN/querying.md at v5 · demopark/sequelize-docs-Zh-CN · GitHub

获取字段 name 值为 anna 的所有记录

1
2
3
4
5
const findList = await userTable.findAll({ where: { name: "anna" } });
for (let i of findList) {
console.log(i.name);
anna;
}

where 还支持运算符操作 sequelize-docs-Zh-CN/querying.md at v5 · demopark/sequelize-docs-Zh-CN · GitHub
先载入 Op 对象

1
const Op = Sequelize.Op;

或操作,返回所有 name 值为 anna 或 ava 的记录

1
2
3
4
5
const findList = await userTable.findAll({
where: {
[Op.or]: [{ name: "anna" }, { name: "ava" }],
},
});

另一种写法

1
2
3
4
5
6
7
const findList = await userTable.findAll({
where: {
name: {
[Op.or]: ["anna", "ava"],
},
},
});

返回所有年龄在范围 [20, 25] 内的记录

1
2
3
4
5
6
7
const findList = await userTable.findAll({
where: {
age: {
[Op.in]: [20, 25],
},
},
});

返回 name 值包含 an 字母的记录

1
2
3
4
5
6
7
const findList = await userTable.findAll({
where: {
name: {
[Op.like]: "%an%",
},
},
});

返回 name 值含有字母 a, 或 age 值为 20 的记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const findModel = await userTable.findAll({
where: {
[Op.or]: [
{
name: {
[Op.substring]: "a"
}
},
{
age: {
[Op.eq]: 20
}
}
]
}
});

order

sequelize-docs-Zh-CN/querying.md at v5 · demopark/sequelize-docs-Zh-CN · GitHub

参考

Sequelize Docs 中文版 | sequelize-docs-Zh-CN
Model | Sequelize