Sequelize 中有两种查询:使用 Model(模型)中的方法查询和使用 sequelize.query() 进行基于 SQL 语句的原始查询。

下面是事先创建好的数据:

mysql> select * from users;
+----+----------+------+------+-------+
| id | name     | age  | sex  | score |
+----+----------+------+------+-------+
|  1 | guodada0 |   15 |    0 |    60 |
|  2 | guodada1 |   16 |    1 |    80 |
|  3 | guodada2 |   17 |    0 |    55 |
|  4 | guodada3 |   18 |    1 |    87 |
|  5 | guodada4 |   19 |    0 |    73 |
|  6 | guodada5 |   20 |    1 |    22 |
+----+----------+------+------+-------+
6 rows in set (0.00 sec)

定义的 model

const UserModel = sequelize.define('user',{name: Sequelize.STRING,age: Sequelize.INTEGER,sex: Sequelize.INTEGER,score: Sequelize.INTEGER},{ timestamps: false }
)

查询多项 (findAll)

const result = await UserModel.findAll() // result 将是所有 UserModel 实例的数组// the same as
const result = await UserModel.all()//...

限制字段

查询时,如果只需要查询模型的部分属性,可以在通过在查询选项中指定 attributes 实现。该选项是一个数组参数,在数组中指定要查询的属性即可,这些要查询的属性就表示要在数据库查询的字段:

Model.findAll({attributes: ['foo', 'bar']
})

字段重命名

查询属性(字段)可以通过传入一个嵌套数据进行重命名:

Model.findAll({attributes: ['foo', ['bar', 'baz']]
})// SELECT foo, bar AS baz ...

demo

const results = await UserModel.findAll({attributes: [['name', 'username'], 'age', 'score']
})// [{"username":"guodada0","age":15,"score":60},{"username":"guodada1","age":16,"score":80} ...]
ctx.body = results// 访问查询结果 通过 instance.get('xxx')
console.log(results[0]['username'], results[0].get('username')) // undefind, 'guodada0'

指定筛选条件 (where)

在模型的 find/finAllupdates/destroys 操作中,可以指定一个 where 选项以指定筛选条件,
where 是一个包含属性/值对对象,sequelize 会根据此对象生产查询语句的筛选条件。

const results = await UserModel.findAll({where: {age: 18,name: 'guodada3'}
}) //  SELECT * FROM `users` AS `user` WHERE `user`.`age` = 18 AND `user`.`name` = 'guodada3';await UserModel.destroy({where: { name: 'guodada3' }
}) // DELETE FROM `users` WHERE name = 'guodada3'// ...

复合过滤 / OR / NOT 查询

$and: {a: 5}           // AND (a = 5)
$or: [{a: 5}, {a: 6}]  // (a = 5 OR a = 6)
$gt: 6,                // > 6
$gte: 6,               // >= 6
$lt: 10,               // < 10
$lte: 10,              // <= 10
$ne: 20,               // != 20
$not: true,            // IS NOT TRUE
$between: [6, 10],     // BETWEEN 6 AND 10
$notBetween: [11, 15], // NOT BETWEEN 11 AND 15
$in: [1, 2],           // IN [1, 2]
$notIn: [1, 2],        // NOT IN [1, 2]
$like: '%hat',         // LIKE '%hat'
$notLike: '%hat'       // NOT LIKE '%hat'
$iLike: '%hat'         // ILIKE '%hat' (case insensitive) (PG only)
$notILike: '%hat'      // NOT ILIKE '%hat'  (PG only)
$like: { $any: ['cat', 'hat']}// LIKE ANY ARRAY['cat', 'hat'] - also works for iLike and notLike
$overlap: [1, 2]       // && [1, 2] (PG array overlap operator)
$contains: [1, 2]      // @> [1, 2] (PG array contains operator)
$contained: [1, 2]     // <@ [1, 2] (PG array contained by operator)
$any: [2,3]            // ANY ARRAY[2, 3]::INTEGER (PG only)$col: 'user.organization_id' // = "user"."organization_id", with dialect specific column identifiers, PG in this example
  • $like: 模糊查询 %锅 结尾的。 %锅% 包含 锅 的
  • $in: [10, 11] - 值为 10 或 11

demo

// SELECT * FROM `users` AS `user` WHERE `user`.`age` > 18 AND `user`.`name` LIKE '%5';
const results = await UserModel.findAll({where: {age: { $gt: 18 },name: { $like: '%5' }}
})// SELECT * FROM `users` AS `user` WHERE (`user`.`age` < 1000 OR `user`.`age` IS NULL) AND `user`.`name` LIKE '%5';
const results = await UserModel.findAll({where: {age: {$in: [15, 20],$or: { $lt: 1000, $eq: null }},name: { $like: '%5' }}
})

分页与限制返回结果数

查询进,我们可以使用 limit 限制返回结果条数,并可以通过 offset 来设置查询偏移(跳过)量,通过这两个属性我们可以实现分页查询的功能:

// 获取 10 条数据(实例)
UserModel.findAll({ limit: 10 })// 跳过 8 条数据(实例)
UserModel.findAll({ offset: 8 })// 跳过 5 条数据并获取其后的 5 条数据(实例)
UserModel.findAll({ offset: 5, limit: 5 })

排序

order 选项用于查询结果的排序数据。排序时应该传入一个包含属性-排序方向的元组/数组,以保证正确的转义:

const result = await UserModel.findAll({order: sequelize.literal('name DESC') // 降序
})// demo2
const result = await UserModel.findAll({order: [sequelize.literal('score DESC'), sequelize.literal('name DESC')]
})// 按 max(age) DESC 排序
[sequelize.fn('max', sequelize.col('age')), 'DESC'],// 按相关联的User 模型的 name 属性排序
[ArticleModel, 'name', 'DESC']// ...

查询单项

// find
const result = await UserModel.find({where: { id: 1 }
})
console.log(result.name, result.get('name')) // guodada0 guodada0// findOne
const result = await UserModel.findOne({where: { id: 1 }
})
console.log(result.name, result.get('name')) // guodada0 guodada0// findById
const result = await UserModel.findById(1)
console.log(result.name, result.get('name')) // guodada0 guodada0// findByPk
const result = await UserModel.findByPk(1)//...

查找并创建 (findOrCreate)

findOrCreate 可用于检测一个不确定是否存在的元素,如果存在则返回记录,不存在时会使用提供的默认值新建记录。

UserModel.findOrCreate({where: { name: 'guodada' },defaults: {age: 23,sex: 1,score: 99}
}).spread((user, created) => {console.log(user.get('name')) // guodadaconsole.log(created) // 是否创建
})// INSERT INTO `users` (`id`,`name`,`age`,`sex`,`score`)
// VALUES (DEFAULT,'guodada',23,1,99);

分页查询 (findAndCountAll)

findAndCountAll - 结合了 findAllcount

处理程序成功将始终接收具有两个属性的对象:

  • count - 一个整数,总数记录匹配 where 语句和关联的其它过滤器
  • rows - 一个数组对象,记录在 limitoffset 范围内匹配 where 语句和关联的其它过滤器
const result = await UserModel.findAndCountAll({where: {age: {$gte: 18 // 大于等于18}},offset: 1, // 偏移量,可以理解为当前页数limit: 15 // 可以理解为 pageSize , 一页有多少数据
})// count 记录数 | row 记录
console.log(result.count, result.rows[0].get())// SELECT * FROM `users` AS `user` WHERE `user`.`age` >= 18 LIMIT 1, 15;

支持 include

它支持 include。 只有标记为 requiredinclude 将被添加到计数部分:

假设你想找 User 中 发布过 article 的记录

const UserModel = sequelize.define('user',{name: Sequelize.STRING,age: Sequelize.INTEGER,sex: Sequelize.INTEGER,score: Sequelize.INTEGER},{ timestamps: false }
)const ArticleModel = sequelize.define('article', {title: Sequelize.STRING,content: Sequelize.STRING
})UserModel.hasMany(ArticleModel) // 关联模型
ArticleModel.belongsTo(UserModel, {constraints: false
})const result = await UserModel.findAndCountAll({include: [{ model: ArticleModel, required: true }],offset: 1,limit: 5
})console.log(result.count) // 3

result.row:

{"count": 3,"rows": [{"id": 1,"name": "guodada0","age": 15,"sex": 0,"score": 60,"article": {"id": 1,"title": "title1","content": "aaa","userId": 1,"createdAt": "2019-01-07T08:51:13.000Z","updatedAt": "2019-01-07T08:51:13.000Z"}}//...]
}

因为 ArticleModelincluderequired 设置,这将导致内部连接,并且只有具有 ArticleModel 的用户将被计数。
如果我们从 include 中删除 required,那么有和没有 ArticleModel 的用户都将被计数。
include 中添加一个 where 语句会自动使它成为 required:

const result = await UserModel.findAndCountAll({include: [{ model: ArticleModel }]
})console.log(result.count) // 7const result = await UserModel.findAndCountAll({include: [{ model: ArticleModel, where: { userId: 2 } }]
})console.log(result.count) // 2

聚合查询

SQL 中的分组查询

mysql-聚合函数

SQL 查询中,通 GROUP BY 语名实现分组查询。GROUP BY 子句要和聚合函数配合使用才能完成分组查询,在 SELECT 查询的字段中,如果没有使用聚合函数就必须出现在 ORDER BY 子句中。分组查询后,查询结果为一个或多个列分组后的结果集。

SELECT 列名, 聚合函数(列名)
FROM 表名
WHERE 列名 operator value
GROUP BY 列名
[HAVING 条件表达式] [WITH ROLLUP]

在以上语句中:

  • 聚合函数 - 分组查询通常要与聚合函数一起使用,聚合函数包括:

    • ***COUNT()***-用于统计记录条数
    • ***SUM()***-用于计算字段的值的总和
    • ***AVG()***-用于计算字段的值的平均值
    • MAX-用于查找查询字段的最大值
    • MIX-用于查找查询字段的最小值
  • GROUP BY 子名-用于指定分组的字段
  • HAVING 子名-用于过滤分组结果,符合条件表达式的结果将会被显示
  • WITH ROLLUP 子名-用于指定追加一条记录,用于汇总前面的数据

sum(field, [options])

Sequelize 提供了聚合函数,可以直接对模型进行聚合查询:

  • aggregate(field, aggregateFunction, [options])-通过指定的聚合函数进行查询
  • sum(field, [options])-求和
  • count(options: Object)-统计查询结果数
  • max(field, [options])-查询最大值
  • min(field, [options])-查询最小值
    以上这些聚合函数中,可以通过 options.attributes、options.attributes 属性指定分组相关字段,并可以通过 options.having 指定过滤条件,但没有直接指定 WITH ROLLUP 子句的参数。

使用**.sum()**查询订单数量大于 1 的用户订单额:

const result = await OrderModel.sum('price', {attributes: ['name', [sequelize.fn('COUNT', sequelize.col('price')), 'sum']],group: 'name',plain: false, // 执行的查询类型,sequelize会根据这个类型对返回结果格式化。having: {$and: [sequelize.literal('COUNT(name) > 1')]}
})// SELECT `name`, SUM(`price`) AS `sum` FROM `orders` AS `order` GROUP BY `name` HAVING (COUNT(name) > 1);// [ { name: 'guo', sum: '44' }, { name: 'guo2', sum: '22' } ]
  • **plain:**执行的查询类型,sequelize 会根据这个类型对返回结果格式化
  • sequelize.literal: 创建一个字面量对象,该值不会转义
    除直接使用聚合函数外,也可以在 **findAll()**等方法中,指定聚合查询相关参数实现聚合查询。
    查询时,同样可以通过通过 options.attributes、options.attributes 属性指定分组相关字段,并可以通过 options.having 指定过滤条件。与直接使用聚合函数查询不一样,通过参数构建聚合查询时,
    要以数组或对象形式设置 options.attributes 参数中的聚合字段,并需要通过 **sequelize.fn()**方法传入聚合函数。
const result = await OrderModel.findAll({attributes: ['name', [sequelize.fn('SUM', sequelize.col('price')), 'sum']],group: 'name',having: {$and: [sequelize.literal('COUNT(name) > 1')]},raw: true // row 对查询结果进行格式化, false 返回 instance
})

sequelize.fn() - 函数调用

sequelize.fn(fn, args) -> Sequelize.fn

创建于一个相当于数据库函数的对象。该函数可用于搜索查询的 whereorder 部分,以及做为列定义的默认值。如果想在列中引用你定义的函数,就要使用 sequelize.col,这样列就能正确的解析,而不是解析为字符串。
如,将 username 字段值解析为大写形式:

instance.updateAttributes({username: self.sequelize.fn('upper', self.sequelize.col('username'))
})

sequelize.col() - 列对象

创建一个相当于数据库列的对象。这个方法经常结合 sequelize.fn 使用,它可以保证将列名正确的传递给该方法,而不是经过转义。

count(options: Object)

const result = await OrderModel.count({where: { price: 24 }
})

max/min

const result = await OrderModel.max('price', {where: {price: { $lt: 23 }}
})

原始查询

原始查询

有时会使用原始查询或执行已准备好的 SQL 语句,这时可以用 Sequlize 提供的工具函数 sequelize.query 来实现。

const result = await sequelize.query('SELECT * FROM users', { model: UserModel })

查询参数替换

原始查询中有两种替换查询参数的方法,以:开头的参数的形式替换或以不命名以?替换。在选项对象中传递参数:

  • 如果传递一个数组,? 会按数组的顺序被依次替换
  • 巢传递一个对象,:key 将会用对象的键替换。如果对象中未找到指定键,则会引发异常(反之亦然)
sequelize.query('SELECT * FROM projects WHERE status = ?', { replacements: ['active'], type: sequelize.QueryTypes.SELECT }).then(function(projects) {console.log(projects)})sequelize.query('SELECT * FROM projects WHERE status = :status ', {replacements: { status: 'active' },type: sequelize.QueryTypes.SELECT}).then(function(projects) {console.log(projects)})

参数绑定

参数绑定类似于参数替换。尤其是参数替换会在发送到数据库前被 sequelize 转义和替换,而参数绑定会被发送到 SQL 查询文本外。

只有 SQLitePostgreSQL 支持参数绑定,其它类型数据库都会将其插入到 SQL 查询,并以相同的方式进行参数替换。参数绑定可以使用$1、$2……或$key 的形式:

  • 如果传入的是数组,$1 会绑定到数组听第 1 个参数 (bind[0])
  • 如果传入一个对象,$key 会绑定到 object[‘key’]。每个 key 必须以非数字的字符开始。$1 不是个有效的 key,尽管 object[‘1’] 是存在的。
  • 在使用$时,不会被转义而是将时,不会被转义而是将时,不会被转义而是将做为一个字面量使用。
    传入的数组或对象必须包含所有绑定值,否则 Sequelize 会抛出异常。这同样适用于数据库可能会忽略绑定参数的情况下。

数据库可能会做进一步限制,绑定参数不能使用数据库关键字,也不能是表或列名,它在引用文本或数据时也可能被忽略。在 PostgreSQL 中,如果不能从上下文$1::varchar 中推断类型,那么也需要进行类型转换

sequelize.query('SELECT *, "text with literal $$1 and literal $$status" as t FROM projects WHERE status = $1', {bind: ['active'],type: sequelize.QueryTypes.SELECT}).then(function(projects) {console.log(projects)})sequelize.query('SELECT *, "text with literal $$1 and literal $$status" as t FROM projects WHERE status = $status', {bind: { status: 'active' },type: sequelize.QueryTypes.SELECT}).then(function(projects) {console.log(projects)})

sequelize 查询相关推荐

  1. Sequelize 查询操作

    Sequelize 是一个基于 promise 的 Node.js ORM 工具, 目前支持 Postgres, MySQL, MariaDB, SQLite 以及 Microsoft SQL Ser ...

  2. NodeJS的Sequelize与Sequelize-cli入门

    1.Sequelize与Sequelize入门 可以查看Sequelize 中文文档:https://www.sequelize.com.cn/ 以及结合下面的代码 进行学习. 1.初始化工作 在no ...

  3. sequelize支持mysql版本_使用Sequelize

    访问MySQL 当我们安装好MySQL后,Node.js程序如何访问MySQL数据库呢? 访问MySQL数据库只有一种方法,就是通过网络发送SQL命令,然后,MySQL服务器执行后返回结果. 我们可以 ...

  4. [转] 关于“时间”的一次探索

    原始链接: https://segmentfault.com/a/1190000004292140 最近使用 sequelize 过程中发现一个"奇怪"的问题,将某个时间插入到表中 ...

  5. Koa2框架生态实战

    补充知识点: 1.git操作相关 git commit -m "refactor:" -> refactor表示修改了目录结构 git commit -m "fix ...

  6. 数据结构与算法(C语言)

    第一章: 数据结构绪论 1.什么是程序:程序 = 数据结构 + 算法 2.逻辑结构&物理结构的区别用法 基本的目标就是将数据及其逻辑关系存储到计算机的内存中 一:逻辑结构: 逻辑结构是指数据对 ...

  7. egg mysql 连表查询_Egg中使用Sequelize框架关联查询Mysql数据库

    Sequelize视频教程_Eggjs仿小米商城企业级Nodejs项目实战视频教程: https://www.itying.com/goods-941.html 一.Sequelize简介 前面的章节 ...

  8. Sequelize 中文文档 v4 - Querying - 查询

    Querying - 查询 此系列文章的应用示例已发布于 GitHub: sequelize-docs-Zh-CN. 可以 Fork 帮助改进或 Star 关注更新. 欢迎 Star. 属性 想要只选 ...

  9. php sequelize,node,express_sequelize 联合查询,node,express,mysql,sequelize - phpStudy

    sequelize 联合查询 我用sequelize 联合查询 db.user.hasMany(db.bbsuser,{foreignKey:'userId'}); db.bbsuser.belong ...

最新文章

  1. weblogic如何在linux扩容,如何在linux的weblogic上增加启动参数
  2. ABAP delete的用法
  3. 一种新的在线学习的方法:能够克服单人多任务学习的困难!
  4. 采取监测记录网络运行状态_广播播控监测自动化系统改造探析
  5. 电脑手写板_点到之处妙笔生花,实用平板电脑手写电容笔推荐
  6. AOS V0.8 发布,JavaEE 应用基础平台
  7. 【Oracle】进阶知识进一步了解
  8. adb echo shell 覆盖_Shell脚本的应用(一)
  9. 软件测试电脑内存适配,利用Memtest86 测试你电脑的内存
  10. python 批量创建文件夹
  11. YOLOv7官方开源 | Alexey Bochkovskiy站台,精度速度超越所有YOLO,还得是AB
  12. DCM 与CCM模式
  13. Base64编码简介
  14. python转换word到html,Python实现批量将word转html并将html内容发布至网站的方法
  15. Macos中的Mercurial GUI工具Murky试用
  16. 电机编码器调零步骤_什么是调零对位?伺服电机编码器调零对位方法
  17. 计算机键盘句号,句号怎么打_键盘句号怎么打_句号怎么打在电脑上-Guide信息网...
  18. 学习是一种态度,优秀是一种习惯
  19. 创业,I have a dream
  20. 搭建机器人电控系统——如何从零画一块主控板?——搭建最小系统电路原理图

热门文章

  1. 读书笔记-Java高级编程-魏勇
  2. 指定的任务可执行文件“sgen.exe”未能运行。System.ComponentModel.Win32Exception
  3. Cannot allocate TUN/TAP dev dynamically
  4. python+selenium+Chrome(无头版)爬取国家地表水水质自动监测实时数据发布系统(修改版)——动态网页爬虫
  5. IOS开发之——xxx has conflicting provisioning settings
  6. 关于局域网及广域网安全的解决办法
  7. lnmp一键安装包linux,linux centos7.3 lnmp一键安装包集成
  8. 5G NR的加扰与解扰
  9. 几分钟学会密码学(一)——维吉尼亚密码
  10. 巨人网络正式推出首款网页游戏