Sequelize官方GitHub:https://github.com/sequelize/sequelize
Sequelize官方中文文檔:https://github.com/demopark/sequelize-docs-Zh-CN
Sequelize官方英文文檔:http://docs.sequelizejs.com/
Querying - 查詢
屬性
想要只選擇某些屬性,可以使用 attributes
選項(xiàng)缴允。 通常是傳遞一個(gè)數(shù)組:
Model.findAll({
attributes: ['foo', 'bar']
});
SELECT foo, bar ...
屬性可以使用嵌套數(shù)組來重命名:
Model.findAll({
attributes: ['foo', ['bar', 'baz']]
});
SELECT foo, bar AS baz ...
也可以使用 sequelize.fn
來進(jìn)行聚合:
Model.findAll({
attributes: [[sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']]
});
SELECT COUNT(hats) AS no_hats ...
使用聚合功能時(shí),必須給它一個(gè)別名,以便能夠從模型中訪問它舆吮。 在上面的例子中袜啃,您可以使用 instance.get('no_hats')
獲得帽子數(shù)量囊陡。
有時(shí),如果您只想添加聚合葱她,則列出模型的所有屬性可能令人厭煩:
// This is a tiresome way of getting the number of hats...
Model.findAll({
attributes: ['id', 'foo', 'bar', 'baz', 'quz', [sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']]
});
// This is shorter, and less error prone because it still works if you add / remove attributes
Model.findAll({
attributes: { include: [[sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']] }
});
SELECT id, foo, bar, baz, quz, COUNT(hats) AS no_hats ...
同樣,它也可以排除一些指定的表字段:
Model.findAll({
attributes: { exclude: ['baz'] }
});
SELECT id, foo, bar, quz ...
Where
無論您是通過 findAll/find 或批量 updates/destroys 進(jìn)行查詢似扔,都可以傳遞一個(gè) where
對象來過濾查詢吨些。
where
通常用 attribute:value 鍵值對獲取一個(gè)對象,其中 value 可以是匹配等式的數(shù)據(jù)或其他運(yùn)算符的鍵值對象虫几。
也可以通過嵌套 or
和 and
運(yùn)算符
的集合來生成復(fù)雜的 AND/OR 條件锤灿。
基礎(chǔ)
const Op = Sequelize.Op;
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.findAll({
where: {
[Op.or]: [{authorId: 12}, {authorId: 13}]
}
});
// SELECT * FROM post WHERE authorId = 12 OR authorId = 13;
Post.findAll({
where: {
authorId: {
[Op.or]: [12, 13]
}
}
});
// SELECT * FROM post WHERE authorId = 12 OR authorId = 13;
Post.destroy({
where: {
status: 'inactive'
}
});
// DELETE FROM post WHERE status = 'inactive';
Post.update({
updatedAt: null,
}, {
where: {
deletedAt: {
[Op.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;
操作符
Sequelize 可用于創(chuàng)建更復(fù)雜比較的符號(hào)運(yùn)算符 -
const Op = Sequelize.Op
[Op.and]: {a: 5} // 且 (a = 5)
[Op.or]: [{a: 5}, {a: 6}] // (a = 5 或 a = 6)
[Op.gt]: 6, // id > 6
[Op.gte]: 6, // id >= 6
[Op.lt]: 10, // id < 10
[Op.lte]: 10, // id <= 10
[Op.ne]: 20, // id != 20
[Op.eq]: 3, // = 3
[Op.not]: true, // 不是 TRUE
[Op.between]: [6, 10], // 在 6 和 10 之間
[Op.notBetween]: [11, 15], // 不在 11 和 15 之間
[Op.in]: [1, 2], // 在 [1, 2] 之中
[Op.notIn]: [1, 2], // 不在 [1, 2] 之中
[Op.like]: '%hat', // 包含 '%hat'
[Op.notLike]: '%hat' // 不包含 '%hat'
[Op.iLike]: '%hat' // 包含 '%hat' (不區(qū)分大小寫) (僅限 PG)
[Op.notILike]: '%hat' // 不包含 '%hat' (僅限 PG)
[Op.regexp]: '^[h|a|t]' // 匹配正則表達(dá)式/~ '^[h|a|t]' (僅限 MySQL/PG)
[Op.notRegexp]: '^[h|a|t]' // 不匹配正則表達(dá)式/!~ '^[h|a|t]' (僅限 MySQL/PG)
[Op.iRegexp]: '^[h|a|t]' // ~* '^[h|a|t]' (僅限 PG)
[Op.notIRegexp]: '^[h|a|t]' // !~* '^[h|a|t]' (僅限 PG)
[Op.like]: { [Op.any]: ['cat', 'hat']} // 包含任何數(shù)組['cat', 'hat'] - 同樣適用于 iLike 和 notLike
[Op.overlap]: [1, 2] // && [1, 2] (PG數(shù)組重疊運(yùn)算符)
[Op.contains]: [1, 2] // @> [1, 2] (PG數(shù)組包含運(yùn)算符)
[Op.contained]: [1, 2] // <@ [1, 2] (PG數(shù)組包含于運(yùn)算符)
[Op.any]: [2,3] // 任何數(shù)組[2, 3]::INTEGER (僅限PG)
[Op.col]: 'user.organization_id' // = 'user'.'organization_id', 使用數(shù)據(jù)庫語言特定的列標(biāo)識(shí)符, 本例使用 PG
范圍選項(xiàng)
所有操作符都支持支持的范圍類型查詢。
請記住辆脸,提供的范圍值也可以定義綁定的 inclusion/exclusion但校。
// 所有上述相等和不相等的操作符加上以下內(nèi)容:
[Op.contains]: 2 // @> '2'::integer (PG range contains element operator)
[Op.contains]: [1, 2] // @> [1, 2) (PG range contains range operator)
[Op.contained]: [1, 2] // <@ [1, 2) (PG range is contained by operator)
[Op.overlap]: [1, 2] // && [1, 2) (PG range overlap (have points in common) operator)
[Op.adjacent]: [1, 2] // -|- [1, 2) (PG range is adjacent to operator)
[Op.strictLeft]: [1, 2] // << [1, 2) (PG range strictly left of operator)
[Op.strictRight]: [1, 2] // >> [1, 2) (PG range strictly right of operator)
[Op.noExtendRight]: [1, 2] // &< [1, 2) (PG range does not extend to the right of operator)
[Op.noExtendLeft]: [1, 2] // &> [1, 2) (PG range does not extend to the left of operator)
組合
{
rank: {
[Op.or]: {
[Op.lt]: 1000,
[Op.eq]: null
}
}
}
// rank < 1000 OR rank IS NULL
{
createdAt: {
[Op.lt]: new Date(),
[Op.gt]: new Date(new Date() - 24 * 60 * 60 * 1000)
}
}
// createdAt < [timestamp] AND createdAt > [timestamp]
{
[Op.or]: [
{
title: {
[Op.like]: 'Boat%'
}
},
{
description: {
[Op.like]: '%boat%'
}
}
]
}
// title LIKE 'Boat%' OR description LIKE '%boat%'
運(yùn)算符別名
Sequelize 允許將特定字符串設(shè)置為操作符的別名 -
const Op = Sequelize.Op;
const operatorsAliases = {
$gt: Op.gt
}
const connection = new Sequelize(db, user, pass, { operatorsAliases })
[Op.gt]: 6 // > 6
$gt: 6 // 等同于使用 Op.gt (> 6)
運(yùn)算符安全性
使用沒有別名的 Sequelize 可以提高安全性。
有些框架會(huì)自動(dòng)將用戶輸入解析為 js 對象啡氢,如果您不能清理輸入的內(nèi)容状囱,則可能會(huì)將具有字符串運(yùn)算符的 Object 注入 Sequelize术裸。
沒有任何字符串別名將使得運(yùn)算符可能被注入的可能性降到極低,但您應(yīng)該始終正確驗(yàn)證和清理用戶輸入亭枷。
為了更好的安全性袭艺,強(qiáng)烈建議在代碼中使用 Sequelize.Op
中的符號(hào)運(yùn)算符,而不是依賴任何字符串別名叨粘。 您可以通過設(shè)置 operatorsAliases
選項(xiàng)來限制應(yīng)用程序需要的別名猾编,請記住要清理用戶輸入,特別是當(dāng)您直接將它們傳遞給 Sequelize 方法時(shí)升敲。
const Op = Sequelize.Op;
// 不用任何操作符別名使用 sequelize
const connection = new Sequelize(db, user, pass, { operatorsAliases: false });
// 只用 $and => Op.and 操作符別名使用 sequelize
const connection2 = new Sequelize(db, user, pass, { operatorsAliases: { $and: Op.and } });
如果你使用默認(rèn)別名并且不限制它們答倡,Sequelize會(huì)發(fā)出警告。如果您想繼續(xù)使用所有默認(rèn)別名(不包括舊版別名)而不發(fā)出警告驴党,您可以傳遞以下運(yùn)算符參數(shù) -
const Op = Sequelize.Op;
const operatorsAliases = {
$eq: Op.eq,
$ne: Op.ne,
$gte: Op.gte,
$gt: Op.gt,
$lte: Op.lte,
$lt: Op.lt,
$not: Op.not,
$in: Op.in,
$notIn: Op.notIn,
$is: Op.is,
$like: Op.like,
$notLike: Op.notLike,
$iLike: Op.iLike,
$notILike: Op.notILike,
$regexp: Op.regexp,
$notRegexp: Op.notRegexp,
$iRegexp: Op.iRegexp,
$notIRegexp: Op.notIRegexp,
$between: Op.between,
$notBetween: Op.notBetween,
$overlap: Op.overlap,
$contains: Op.contains,
$contained: Op.contained,
$adjacent: Op.adjacent,
$strictLeft: Op.strictLeft,
$strictRight: Op.strictRight,
$noExtendRight: Op.noExtendRight,
$noExtendLeft: Op.noExtendLeft,
$and: Op.and,
$or: Op.or,
$any: Op.any,
$all: Op.all,
$values: Op.values,
$col: Op.col
};
const connection = new Sequelize(db, user, pass, { operatorsAliases });
JSON
JSON 數(shù)據(jù)類型僅由 PostgreSQL瘪撇,SQLite 和 MySQL 語言支持。
PostgreSQL
PostgreSQL 中的 JSON 數(shù)據(jù)類型將值存儲(chǔ)為純文本港庄,而不是二進(jìn)制表示倔既。 如果您只是想存儲(chǔ)和檢索 JSON 格式數(shù)據(jù),那么使用 JSON 將占用更少的磁盤空間鹏氧,并且從其輸入數(shù)據(jù)中構(gòu)建時(shí)間更少渤涌。 但是,如果您想對 JSON 值執(zhí)行任何操作度帮,則應(yīng)該使用下面描述的 JSONB 數(shù)據(jù)類型歼捏。
MSSQL
MSSQL 沒有 JSON 數(shù)據(jù)類型,但是它確實(shí)提供了對于自 SQL Server 2016 以來通過某些函數(shù)存儲(chǔ)為字符串的 JSON 的支持笨篷。使用這些函數(shù)瞳秽,您將能夠查詢存儲(chǔ)在字符串中的 JSON,但是任何返回的值將需要分別進(jìn)行解析率翅。
// ISJSON - 測試一個(gè)字符串是否包含有效的 JSON
User.findAll({
where: sequelize.where(sequelize.fn('ISJSON', sequelize.col('userDetails')), 1)
})
// JSON_VALUE - 從 JSON 字符串提取標(biāo)量值
User.findAll({
attributes: [[ sequelize.fn('JSON_VALUE', sequelize.col('userDetails'), '$.address.Line1'), 'address line 1']]
})
// JSON_VALUE - 從 JSON 字符串中查詢標(biāo)量值
User.findAll({
where: sequelize.where(sequelize.fn('JSON_VALUE', sequelize.col('userDetails'), '$.address.Line1'), '14, Foo Street')
})
// JSON_QUERY - 提取一個(gè)對象或數(shù)組
User.findAll({
attributes: [[ sequelize.fn('JSON_QUERY', sequelize.col('userDetails'), '$.address'), 'full address']]
})
JSONB
JSONB 可以以三種不同的方式進(jìn)行查詢练俐。
嵌套對象
{
meta: {
video: {
url: {
[Op.ne]: null
}
}
}
}
嵌套鍵
{
"meta.audio.length": {
[Op.gt]: 20
}
}
外包裹
{
"meta": {
[Op.contains]: {
site: {
url: 'http://google.com'
}
}
}
}
關(guān)系 / 關(guān)聯(lián)
// 找到所有具有至少一個(gè) task 的 project,其中 task.state === project.state
Project.findAll({
include: [{
model: Task,
where: { state: Sequelize.col('project.state') }
}]
})
分頁 / 限制
// 獲取10個(gè)實(shí)例/行
Project.findAll({ limit: 10 })
// 跳過8個(gè)實(shí)例/行
Project.findAll({ offset: 8 })
// 跳過5個(gè)實(shí)例冕臭,然后取5個(gè)
Project.findAll({ offset: 5, limit: 5 })
排序
order
需要一個(gè)條目的數(shù)組來排序查詢或者一個(gè) sequelize 方法腺晾。一般來說,你將要使用任一屬性的 tuple/array辜贵,并確定排序的正反方向悯蝉。
Subtask.findAll({
order: [
// 將轉(zhuǎn)義標(biāo)題,并根據(jù)有效的方向參數(shù)列表驗(yàn)證DESC
['title', 'DESC'],
// 將按最大值排序(age)
sequelize.fn('max', sequelize.col('age')),
// 將按最大順序(age) DESC
[sequelize.fn('max', sequelize.col('age')), 'DESC'],
// 將按 otherfunction 排序(`col1`, 12, 'lalala') DESC
[sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],
// 將使用模型名稱作為關(guān)聯(lián)的名稱排序關(guān)聯(lián)模型的 created_at托慨。
[Task, 'createdAt', 'DESC'],
// Will order through an associated model's created_at using the model names as the associations' names.
[Task, Project, 'createdAt', 'DESC'],
// 將使用關(guān)聯(lián)的名稱由關(guān)聯(lián)模型的created_at排序鼻由。
['Task', 'createdAt', 'DESC'],
// Will order by a nested associated model's created_at using the names of the associations.
['Task', 'Project', 'createdAt', 'DESC'],
// Will order by an associated model's created_at using an association object. (優(yōu)選方法)
[Subtask.associations.Task, 'createdAt', 'DESC'],
// Will order by a nested associated model's created_at using association objects. (優(yōu)選方法)
[Subtask.associations.Task, Task.associations.Project, 'createdAt', 'DESC'],
// Will order by an associated model's created_at using a simple association object.
[{model: Task, as: 'Task'}, 'createdAt', 'DESC'],
// 嵌套關(guān)聯(lián)模型的 created_at 簡單關(guān)聯(lián)對象排序
[{model: Task, as: 'Task'}, {model: Project, as: 'Project'}, 'createdAt', 'DESC']
]
// 將按年齡最大值降序排列
order: sequelize.literal('max(age) DESC')
// 按最年齡大值升序排列,當(dāng)省略排序條件時(shí)默認(rèn)是升序排列
order: sequelize.fn('max', sequelize.col('age'))
// 按升序排列是省略排序條件的默認(rèn)順序
order: sequelize.col('age')
// 將根據(jù)方言隨機(jī)排序 (而不是 fn('RAND') 或 fn('RANDOM'))
order: sequelize.random()
})
Table Hint
當(dāng)使用 mssql 時(shí),可以使用 tableHint
來選擇傳遞一個(gè)表提示蕉世。 該提示必須是來自 Sequelize.TableHints
的值蔼紧,只能在絕對必要時(shí)使用。 每個(gè)查詢當(dāng)前僅支持單個(gè)表提示狠轻。
表提示通過指定某些選項(xiàng)來覆蓋 mssql 查詢優(yōu)化器的默認(rèn)行為奸例。 它們只影響該子句中引用的表或視圖。
const TableHints = Sequelize.TableHints;
Project.findAll({
// 添加 table hint NOLOCK
tableHint: TableHints.NOLOCK
// 這將生成 SQL 'WITH (NOLOCK)'
})