[转]Sequelize 中文API文档-4. 查询与原始查询
本文转自:https://itbilu.com/nodejs/npm/VJIR1CjMb.html
Sequelize
中有两种查询:使用Model
(模型)中的方法查询和使用sequelize.query()
进行基于SQL语句的原始查询。
1. Model
查询
Model
是一种表示与数据库中表关系的描述对象,它通过sequlize.define
方法定义或通过sequlize.import
导入创建实例对象。通过Model
进行进行数据查询时,我们可以实现类似在数据库中直接使用SQL语句的查询、排序、分组、别名、连接查询等。
1.1 Attributes - 属性与查询字段
查询时,如果只需要查询模型的部分属性,可以在通过在查询选项中指定attributes
实现。该选项是一个数组参数,在数组中指定要查询的属性即可,这些要查询的属性就表示要在数据库查询的字段:
Model.findAll({
attributes: ['foo', 'bar']
});
SELECT foo, bar ...
查询属性(字段)可以通过传入一个嵌套数据进行重命名:
Model.findAll({
attributes: ['foo', ['bar', 'baz']]
});
SELECT foo, bar AS baz ...
通过sequelize.fn
方法可以进行聚合查询:
Model.findAll({
attributes: [[sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']]
});
SELECT COUNT(hats) AS no_hats ...
在使用聚合函数时,要给聚合字段指定一个别名。如,在上例中我们为聚合函数指定了别名'no_hats'
,这样我们就能在查询的回调函数实例中通过instance.get('no_hats')
来访问聚合统计的结果。
当需要查询所有字段并对某一字段使用聚合查询时,而只需要以对象的形式传入attributes
并添加include
子属性即可。
// 拽定全查询字段比较麻烦
Model.findAll({
attributes: ['id', 'foo', 'bar', 'baz', 'quz', [sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']]
}); // 这样会比较简短,且在你添加/删除属性后不会出错
Model.findAll({
attributes: { include: [[sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']] }
});
SELECT id, foo, bar, baz, quz, COUNT(hats) AS no_hats ...
全部查询时,可以通过exclude
子属性来排除不需要查询的字段:
Model.findAll({
attributes: { exclude: ['baz'] }
});
SELECT id, foo, bar, quz ...
关于聚合查询,请参考:在Sequelize中使用group by分组聚合查询
1.2 Where - 指定筛选条件
在模型的 find/finAll 或 updates/destroys 操作中,可以指定一个where
选项以指定筛选条件,
where
是一个包含属性/值对对象,sequelize会根据此对象生产查询语句的筛选条件。
基本用法
Post.findAll({
where: {
authorId: 2
}
});
// SELECT * FROM post WHERE authorId = 2 Post.findAll({
where: {
authorId: 12,
status: 'active'
}
});
// SELECT * FROM post WHERE authorId = 12 AND status = 'active'; Post.destroy({
where: {
status: 'inactive'
}
});
// DELETE FROM post WHERE status = 'inactive'; Post.update({
updatedAt: null,
}, {
where: {
deletedAt: {
$ne: null
}
}
});
// UPDATE post SET updatedAt = null WHERE deletedAt NOT NULL; Post.findAll({
where: sequelize.where(sequelize.fn('char_length', sequelize.col('status')), 6)
});
// SELECT * FROM post WHERE char_length(status) = 6;
操作符
$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
组合查询
{
rank: {
$or: {
$lt: 1000,
$eq: null
}
}
}
// rank < 1000 OR rank IS NULL {
createdAt: {
$lt: new Date(),
$gt: new Date(new Date() - 24 * 60 * 60 * 1000)
}
}
// createdAt < [timestamp] AND createdAt > [timestamp] {
$or: [
{
title: {
$like: 'Boat%'
}
},
{
description: {
$like: '%boat%'
}
}
]
}
// title LIKE 'Boat%' OR description LIKE '%boat%'
嵌套对象
{
meta: {
video: {
url: {
$ne: null
}
}
}
}
嵌套键
{
"meta.audio.length": {
$gt: 20
}
}
包含
{
"meta": {
$contains: {
site: {
url: 'http://itbilu.com'
}
}
}
}
关系/联合
// 查询所有至少有一个task的projects,task.state === project.task
Project.findAll({
include: [{
model: Task,
where: { state: Sequelize.col('project.state') }
}]
})
1.3 limit/offset - 分页与限制返回结果数
查询进,我们可以使用limit
限制返回结果条数,并可以通过offset
来设置查询偏移(跳过)量,通过这两个属性我们可以实现分页查询的功能:
// 获取 10 条数据(实例)
Project.findAll({ limit: 10 }) // 跳过 8 条数据(实例)
Project.findAll({ offset: 8 }) // 跳过 5 条数据并获取其后的 5 条数据(实例)
Project.findAll({ offset: 5, limit: 5 })
1.4 查询排序
order
选项用于查询结果的排序数据。排序时应该传入一个包含属性-排序方向的元组/数组,以保证正确的转义:
something.findOne({
order: [
// 转义 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'], // 按相关联的User 模型的 name 属性排序
[User, 'name', 'DESC'], // 按相关联的User 模型的 name 属性排序并将模型起别名为 Friend
[{model: User, as: 'Friend'}, 'name', 'DESC'], // 按相关联的User 模型的嵌套关联的 Company 模型的 name 属性排序
[User, Company, 'name', 'DESC'],
]
// 以下所有声明方式都会视为字面量,应该小心使用
order: 'convert(user_name using gbk)'
order: 'username DESC'
order: sequelize.literal('convert(user_name using gbk)')
})
2. 原始查询
有时会使用原始查询或执行已准备好的SQL语句,这时可以用Sequlize提供的工具函数sequelize.query
来实现。
2.1 原始查询方法
默认情况下,该函数会返回两个参数 - 一个包含结果的数组和一个包含原数据对象。请注意,由于是原始查询,所以返回的元数据与使用的数据库类型有关,其对元数据的处理并不一致。
sequelize.query("UPDATE users SET y = 42 WHERE x = 12").spread(function(results, metadata) {
// Results 会是一个空数组和一个包含受影响行数的metadata 元数据对象
})
如果不想使用元数据,可以查询时指定表示查询类型的type
参数,以告诉sequelize 应该怎样去格式化返回结果。
sequelize.query("SELECT * FROM `users`", { type: sequelize.QueryTypes.SELECT})
.then(function(users) {
// 并不需要在这spread 展开结果,因为所返回的只有所查询的结果
})
在选项参数中,可以使用model
参数指定一个模型,指定后会将查询结果会是传入模型的实例:
// 调用已定义的模型并对其创建实例
sequelize.query('SELECT * FROM projects', { model: Projects }).then(function(projects){
// 每条记录都是一个Project 实例
})
2.2 查询参数替换
原始查询中有两种替换查询参数的方法,以:
开头的参数的形式替换或以不命名以?
替换。在选项对象中传递参数:
- 如果传递一个数组,
?
会按数组的顺序被依次替换 - 巢传递一个对象,
: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)
})
2.3 参数绑定
参数绑定类似于参数替换。尤其是参数替换会在发送到数据库前被sequelize转义和替换,而参数绑定会被发送到SQL 查询文本外。
只有SQLite 和 PostgreSQL支持参数绑定,其它类型数据库都会将其插入到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 中文API文档-4. 查询与原始查询的更多相关文章
- Sequelize 中文API文档-1. 快速入门、Sequelize类
1. https://itbilu.com/nodejs/npm/VkYIaRPz-.html#api-init 2. http://docs.sequelizejs.com/manual/tutor ...
- Android多媒体--MediaCodec 中文API文档
*由于工作需要,需要利用MediaCodec实现Playback及Transcode等功能,故在学习过程中翻译了Google官方的MediaCodec API文档,由于作者水平限制,文中难免有错误和不 ...
- Bootstrap FileInput中文API文档
Bootstrap FileInput中文API整理 这段时间做项目用到bootstrap fileinput插件上传文件,在用的过程中,网上能查到的api都不是很全,所以想着整理一份比较详细的文档, ...
- POI中文API文档
一. POI简介 Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. 二. HSSF概况 HSSF 是 ...
- jquery.Inputmask 插件用法(中文API文档)
jquery.Inputmask 可以算是input文本输入限制的神器了,内部融合了多种输入限制, 如金额,电话号码,身份证号,网关等..,并且还可以自定义规则. inputmask 据说最早起源 ...
- JspSmartUpload 简略中文API文档
感谢原文作者:~数字人生~ 原文链接:https://www.cnblogs.com/mycodelife/archive/2009/04/26/1444132.html 一.JspSmartUplo ...
- Java-UrlRewrite中文api文档
安装 1. 下载jar包, 并加入到WEB-INF/lib下 2. 在WEB-INF/web.xml中增加下面的配置 <filter> <filter-name>UrlRewr ...
- 蓝牙中文API文档
蓝牙是一种低成本.短距离的无线通信技术.对于那些希望创建个人局域网(PANs)的人们来说,蓝牙技术已经越来越流行了.每个个人局域网都在独立设备的周围被动态地创建,并且为蜂窝式电话和PDA等设备提供了自 ...
- (转载)中文Appium API 文档
该文档是Testerhome官方翻译的源地址:https://github.com/appium/appium/tree/master/docs/cn官方网站上的:http://appium.io/s ...
随机推荐
- C# WebAPI系列(1)
WebApi是微软在VS2012 MVC4版本中绑定发行的,WebApi是完全基于Restful标准的框架.RestFul: (英文:Representational State Transfer,简 ...
- VMware安装xp虚拟机
VMware安装xp虚拟机 1.用到的软件: 2.安装VMware: 接受 选择自定义 要等上一小会. 输入密钥:百度一个就可以了. 安装成功: 禁用VMware网卡: 3.安装xp系统: 创建新的 ...
- QEMU KVM Libvirt手册(5) – snapshots
前面讲了QEMU的qcow2格式的internal snapshot和external snapshot,这都是虚拟机文件格式的功能. 这是文件级别的. 还可以是文件系统级别的,比如很多文件系统支持s ...
- spring mvc jsonp调用示例
服务端代码:主要是返回的时候,返回值要用callback包装一下 /** * JSONP调用 * * @param request * @return */ @RequestMapping(" ...
- 宝塔面板下安装zabbix
宝塔面板之前已经安装完成,如果不会可以查看上一个日志.接下来开始安装zabbix 1.添加系统用户和组 2. yum -y install epel-release #安装源 3.使用命令 yum - ...
- Javascript高级编程学习笔记(47)—— 元素遍历
元素遍历 为了方便我们使用JS来遍历文档中的元素,W3C在原来的基础之上提出了 Element Traversal 规范 这一规范主要就是为了统一浏览器对文档中节点解析不一致的问题. 比如在某些浏览器 ...
- Java 11 究竟比 8 快了多少?
阅读本文大概需要 1.2 分钟. 作者:h4cd 来源:开源中国社区 开源规划调度引擎 OptaPlanner 官网发布了一个 Java 11 GC 性能基准测试报告. 当前使用量最大的 Java 版 ...
- JavaPoet开源项目的使用
一.介绍 JavaPoet项目可以动态的生成Java文件,这是一个很强大和很动态的方法,使用注解的时候假如需要生成新的Java文件就可以通过这个开源项目实现. 项目地址:https://github. ...
- Tools - 速查表与备忘单(Cheat Sheet)
Cheat Sheets Rico's cheatsheets Cheat-Sheets.org Python Python Cheat sheet Python Programming Cheat ...
- linux mint 安装 opencv2.4
Download opencv https://github.com/opencv/opencv/tree/2.4 安装必要的依赖 sudo apt-get install build-essenti ...