knex 使用
SQL Query Builder for Javascript | Knex.js
首先下载
npm install knex
使用
const knex = require('knex')({
client: 'mysql',
connection: {
host: 'localhost', // 地址
user: 'root', // 账号
password: '123456', // 密码
database: 'user' // 数据库
}
});
/**
* knex 查询那个表
* select 查询的字段
* where 查询字段数据
*/
knex('user').select('login_name', 'password').where({ login_name: loginName });
knex提供了函数来拦截数据(类似于生命周期)
这些钩子函数可以通过调用knex.on()方法进行注册,在查询被执行时会按照注册的顺序依次调用这些钩子函
// before: 该钩子函数在查询被执行前被调用,可以用来修改查询参数或验证用户权限等操作。
knex.on('query', (data) => {
console.log('before query:', data)
});
// after: 该钩子函数在查询被执行后被调用,可以用来处理查询结果或记录查询日志等操作。
knex.on('query-response', (data) => {
console.log('after query:', data)
});
// error: 该钩子函数在查询发生错误时被调用,可以用来记录错误信息或通知开发人员等操作。
knex.on('query-error', (error, data) => {
console.log('query error:', error, data)
})
knex 批量新增数据
使用 Knex 批量插入数据可以通过 insert
方法的链式调用实现。具体实现步骤如下:
-
准备数据,将需要插入的数据存储在数组中。
-
调用
insert
方法,传入数组参数。
下面是一个示例代码:
复制const data = [
{ name: 'Alice', age: 20 },
{ name: 'Bob', age: 21 },
{ name: 'Charlie', age: 22 }
];
knex('users').insert(data)
.then(() => console.log('Data inserted successfully'))
.catch((err) => console.error(err));
在上面的示例中,我们将一个包含 3 条记录的数组 data
批量插入到 users
表中。insert
方法返回一个 Promise,当插入操作完成时,我们可以在 then
中执行后续操作,例如打印成功信息;当插入操作失败时,我们可以在 catch
中捕获错误并执行相应的错误处理逻辑。
分页
const express = require('express');
const knex = require('knex');
const app = express();
// 连接到数据库
const db = knex({
client: 'sqlite3',
connection: {
filename: './database.sqlite'
}
});
// 分页接口
app.get('/api/users', async (req, res) => {
const page = req.query.page || 1; // 当前页码
const perPage = req.query.perPage || 10; // 每页条目数
const offset = (page - 1) * perPage; // 偏移量
// 查询总数
const countQuery = db('users').count('id as count');
const [{ count }] = await countQuery;
// 查询分页数据
const dataQuery = db('users')
.select('id', 'name', 'email')
.limit(perPage)
.offset(offset);
const data = await dataQuery;
res.json({
data,
totalCount: count,
currentPage: page,
perPage
});
});
app.listen(3000, () => {
console.log('Server started on http://localhost:3000')
});
sequelize
Sequelize 是一个基于 promise 的 Node.js ORM, 目前支持 Postgres, MySQL, MariaDB, SQLite 以及 Microsoft SQL Server. 它具有强大的事务支持, 关联关系, 预读和延迟加载,读取复制等功能。
模型查询(基础) | Sequelize中文文档 | Sequelize中文网
Sequelize 遵从 语义版本控制。 支持 Node v10 及更高版本以便使用 ES6 功能。
连接数据库
这里采用myslq 数据库进行连接
yarn add mysql2 sequelize
const { Sequelize, Model, DataTypes
} = require("sequelize");
const connect = async () => {
const sequelize = new Sequelize("数据库名字",
"用户",
"密码",
{
host: "", // 地址
dialect: "mysql", // 类型
port: 3306, // 端口
timezone: "+08:00",
define: {
timestamps: false, //true表示给模型加上时间戳属性(createAt、updateAt),false表示不带时间戳属性
freezeTableName: true, //true表示使用给定的表名,false表示模型名后加s作为表名
}
});
};
module.exports = connect;
简单使用完成增删改查
建立表的模型
简单封装一下
const { DataTypes } = require("sequelize");
const sequelize = require("../config/database");
const { v4: uuid } = require("uuid")
const errorModule = async () => {
const model = sequelize.define("sys_errors", {
id: {
type: DataTypes.STRING,
allowNull: false,
primaryKey: true,
defaultValue: uuid().replace(/-/g, "") // id默认值
},
host: {
type: DataTypes.STRING
},
name: {
type: DataTypes.STRING
},
requestURL: {
type: DataTypes.STRING,
field: "request_url"
},
createTime: {
type: 'datetime',
field: "create_time"
},
})
return model.sync({ force: false });
}
module.exports = errorModule
简单查询
attributes: 查询当前表的哪些字段
where: 条件
order: 用来定义排序规则
limit 查询的数量
offset: 偏移数量 limit通常配合offset来实现分页查询
User.findAll({
attributes: [],
where: {},
order: [
["createTime", "DESC"], // 按 createTime 字段降序排序
],
limit:0,
offset:0,
});
简单新增
params: 创建的数据
User.create(params);
简单修改
params 修改的参数
where 条件
// 将所有没有姓氏的人更改为 "Doe"
await User.update({ lastName: "Doe" }, {
where: {
lastName: null
}
});
简单删除
// 删除所有名为 "Jane" 的人
await User.destroy({
where: {
firstName: "Jane"
}
});
SELECT 查询特定属性
选择某些特定属性,可以使用 attributes
参数:
Model.findAll({
attributes: ['foo', 'bar']
});
可以使用嵌套数组来重命名属性:
Model.findAll({
attributes: ['foo', ['bar', 'baz'], 'qux']
});
SELECT foo, bar AS baz, qux FROM ...
你可以使用 sequelize.fn 进行聚合:
Model.findAll({
attributes: [
'foo',
[sequelize.fn('COUNT', sequelize.col('hats')), 'n_hats'],
'bar'
]
});
SELECT foo, COUNT(hats) AS n_hats, bar FROM ...
查询总数
where查询的条件
const amount = await User.count({
where: {
}
});
max
, min
和 sum
Sequelize 还提供了 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
排序和分组
User.findAll({
order: [
// 将转义 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()
});
Foo.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']
]
});
基本使用完成增删改查
多表关联查询
比如我们有两个表, 一个user用户表, 一个dept部门表
需求: 查询用户要返回用户的部门信息
User 表示user的模型, Dept 代表dept的模型
我们通过使用 hasMany 和 belongsTo 来实现关联
在这里我们是根据用户查部门, 用户表为主, 部门表为次
hasOne:有一个,加上主谓语应该是 ,1有一个 2
hasMany:有很多,1 有很多 2
belongsTo:属于, 1属于 2
表2.hasMany(表1,{foreignKey: 表1中关联字段 , targetKey: 表2中的字段 })
表1.belongsTo(表2, {
foreignKey: 表1中关联字段,
targetKey: 表2中的关联字段,
});
Dept.hasMany(User, { foreignKey: "deptid", targetKey: "id" });
User.belongsTo(Dept, {
foreignKey: "id",
targetKey: "deptId",
});
Sequelize 支持标准关联关系: 一对一, 一对多 和 多对多.
为此,Sequelize 提供了 四种 关联类型,并将它们组合起来以创建关联:
HasOne
关联类型BelongsTo
关联类型HasMany
关联类型BelongsToMany
关联类型
该指南将讲解如何定义这四种类型的关联,然后讲解如何将它们组合来定义三种标准关联类型(一对一, 一对多 和 多对多).
const A = sequelize.define('A', /* ... */);
const B = sequelize.define('B', /* ... */);
A.hasOne(B); // A 有一个 B
A.belongsTo(B); // A 属于 B
A.hasMany(B); // A 有多个 B
A.belongsToMany(B, { through: 'C' }); // A 属于多个 B , 通过联结表 C
创建一个 一对一 关系, hasOne 和 belongsTo 关联一起使用;
创建一个 一对多 关系, hasMany he belongsTo 关联一起使用;
创建一个 多对多 关系, 两个 belongsToMany 调用一起使用
A.hasOne(B) 关联意味着 A 和 B 之间存在一对一的关系,外键在目标模型(B)中定义.
A.belongsTo(B)关联意味着 A 和 B 之间存在一对一的关系,外键在源模型中定义(A).
A.hasMany(B) 关联意味着 A 和 B 之间存在一对多关系,外键在目标模型(B)中定义.
操作符
Sequelize 提供了多种运算符.
const { Op } = require("sequelize");
Post.findAll({
where: {
[Op.and]: [{ a: 5 }, { b: 6 }], // (a = 5) AND (b = 6)
[Op.or]: [{ a: 5 }, { b: 6 }], // (a = 5) OR (b = 6)
someAttribute: {
// 基本
[Op.eq]: 3, // = 3
[Op.ne]: 20, // != 20
[Op.is]: null, // IS NULL
[Op.not]: true, // IS NOT TRUE
[Op.or]: [5, 6], // (someAttribute = 5) OR (someAttribute = 6)
// 使用方言特定的列标识符 (以下示例中使用 PG):
[Op.col]: 'user.organization_id', // = "user"."organization_id"
// 数字比较
[Op.gt]: 6, // > 6
[Op.gte]: 6, // >= 6
[Op.lt]: 10, // < 10
[Op.lte]: 10, // <= 10
[Op.between]: [6, 10], // BETWEEN 6 AND 10
[Op.notBetween]: [11, 15], // NOT BETWEEN 11 AND 15
// 其它操作符
[Op.all]: sequelize.literal('SELECT 1'), // > ALL (SELECT 1)
[Op.in]: [1, 2], // IN [1, 2]
[Op.notIn]: [1, 2], // NOT IN [1, 2]
[Op.like]: '%hat', // LIKE '%hat'
[Op.notLike]: '%hat', // NOT LIKE '%hat'
[Op.startsWith]: 'hat', // LIKE 'hat%'
[Op.endsWith]: 'hat', // LIKE '%hat'
[Op.substring]: 'hat', // LIKE '%hat%'
[Op.iLike]: '%hat', // ILIKE '%hat' (不区分大小写) (仅 PG)
[Op.notILike]: '%hat', // NOT ILIKE '%hat' (仅 PG)
[Op.regexp]: '^[h|a|t]', // REGEXP/~ '^[h|a|t]' (仅 MySQL/PG)
[Op.notRegexp]: '^[h|a|t]', // NOT REGEXP/!~ '^[h|a|t]' (仅 MySQL/PG)
[Op.iRegexp]: '^[h|a|t]', // ~* '^[h|a|t]' (仅 PG)
[Op.notIRegexp]: '^[h|a|t]', // !~* '^[h|a|t]' (仅 PG)
[Op.any]: [2, 3], // ANY (ARRAY[2, 3]::INTEGER[]) (PG only)
[Op.match]: Sequelize.fn('to_tsquery', 'fat & rat') // 匹配文本搜索字符串 'fat' 和 'rat' (仅 PG)
// 在 Postgres 中, Op.like/Op.iLike/Op.notLike 可以结合 Op.any 使用:
[Op.like]: { [Op.any]: ['cat', 'hat'] } // LIKE ANY (ARRAY['cat', 'hat'])
// 还有更多的仅限 postgres 的范围运算符,请参见下文
}
}
});
断点工具调试
谷歌浏览器进入
chrome://inspect/#devices
是这个界面
项目启动程序中
加入 inspect
node --inspect app.js
此时打开 chrome://inspect/#devices
点击inspect
此时就已经进入断点调试工具
了Knex之外,还有以下几个Node.js中类似于Knex的模块:
-
Sequelize:一个基于Promise的ORM框架,支持PostgreSQL、MySQL、MariaDB、SQLite和Microsoft SQL Server。
-
Bookshelf:一个ORM框架,基于Knex构建,支持PostgreSQL、MySQL和SQLite。
-
Massive.js:一个数据访问库,支持PostgreSQL、MySQL、MariaDB、SQLite、Amazon Redshift和CockroachDB。
-
TypeORM:一个ORM框架,支持MySQL、PostgreSQL、MariaDB、SQLite、Microsoft SQL Server、Oracle、WebSQL等数据库。
-
Waterline:一个ORM框架,支持多种数据源,包括MySQL、PostgreSQL、MongoDB、Redis、API等。
这些模块都提供了类似于Knex的功能,使得Node.js应用程序能够更方便地与各种数据库进行交互。