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 功能。
连接数据库
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应用程序能够更方便地与各种数据库进行交互。