Nodejs?Sequelize手冊(cè)學(xué)習(xí)快速入門(mén)到應(yīng)用
1.連接數(shù)據(jù)庫(kù)(js/ts)
// config.js exports const config = { database: { database: 'management', host: 'localhost', port: 3306, user: 'root', password: '12345678' } }
// db.js const Sequelize = require('sequelize'); import { config } from './config'; const { database, host, port, user, password } = config; const sequelize = new Sequelize(database, user, password, { dialect: 'mysql', host, port, logging: true, // logging: true, 打印sql到控制臺(tái) timezone: '+08:00', //時(shí)間上的統(tǒng)一,這里是東八區(qū),默認(rèn)為0時(shí)區(qū) define: { //全局的定義,會(huì)通過(guò)連接實(shí)例傳遞 // timestamps: false, //默認(rèn)情況下,Sequelize 使用數(shù)據(jù)類(lèi)型 DataTypes.DATE 自動(dòng)向每個(gè)模 型添加 createdAt 和 updatedAt 字段. 這些字段會(huì)自動(dòng)進(jìn)行管理 - 每當(dāng) 你使用Sequelize 創(chuàng)建或更新內(nèi)容時(shí),這些字段都會(huì)被自動(dòng)設(shè)置. createdAt 字段將包含代表創(chuàng)建時(shí)刻的時(shí)間戳,而 updatedAt 字段將包含 最新更新的時(shí)間戳. //對(duì)于帶有timestamps: false 參數(shù)的模型,可以禁用此行為 // createdAt: 'created_at', //自定義時(shí)間戳 // updatedAt: 'updated_at', // paranoid: true, // deletedAt: 'deleted_at', //paranoid表示在被告之要?jiǎng)h除記錄時(shí)并不會(huì)真正的物理上刪除,而 是添加一個(gè)存有刪除請(qǐng)求時(shí)間戳deletedAt的特殊字段。傳遞 paranoid: true參數(shù)給模型定義中。paranoid要求必須啟用時(shí)間戳, 即必須傳timestamps: true // 把駝峰命名轉(zhuǎn)換為下劃線 //underscored: false, pool: { // 使用連接池 max: 5, // 連接池中最大連接數(shù)量 min: 0, // 連接池中最小連接數(shù)量 acquire: 30000, idle: 10000 // 如果一個(gè)線程 10 秒鐘內(nèi)沒(méi)有被使用過(guò)的話,那么就釋放線程 }, } }) // 測(cè)試數(shù)據(jù)庫(kù)鏈接 sequelize .authenticate() .then(() => { console.log('數(shù)據(jù)庫(kù)連接成功'); }) .catch((err: any) => { // 數(shù)據(jù)庫(kù)連接失敗時(shí)打印輸出 console.error(err); throw err; }); export default sequelize; // 將連接對(duì)象暴露出去
2.數(shù)據(jù)庫(kù)模型
1.模型定義
調(diào)用sequelize.define(modelName, attributes, options)
const User = sequelize.define('User', { // 在這里定義模型屬性 id: { type: DataTypes.INTEGER, autoIncrement: true, //允許自增 primaryKey: true } firstName: { type: DataTypes.STRING, allowNull: false }, lastName: { type: DataTypes.STRING // allowNull 默認(rèn)為 true } }, { // 這是其他模型參數(shù) sequelize, // 我們需要傳遞連接實(shí)例 //局部的定義 modelName: 'User' // 我們需要選擇模型名稱(chēng) // 不要忘記啟用時(shí)間戳! timestamps: true, // 不想要 createdAt createdAt: false, // 想要 updatedAt 但是希望名稱(chēng)叫做 updateTimestamp updatedAt: 'updateTimestamp' }); // `sequelize.define` 會(huì)返回模型 console.log(User === sequelize.models.User); // true
時(shí)間戳(timestamps)
默認(rèn)情況下,Sequelize 使用數(shù)據(jù)類(lèi)型 DataTypes.DATE
自動(dòng)向每個(gè)模型添加 createdAt
和 updatedAt
字段. 這些字段會(huì)自動(dòng)進(jìn)行管理 - 每當(dāng)你使用Sequelize 創(chuàng)建或更新內(nèi)容時(shí),這些字段都會(huì)被自動(dòng)設(shè)置. createdAt
字段將包含代表創(chuàng)建時(shí)刻的時(shí)間戳,而 updatedAt
字段將包含最新更新的時(shí)間戳.
對(duì)于帶有 timestamps: false
參數(shù)的模型,可以禁用此行為,要啟用createdAt,updatedAt必須要 timestamps: true
:
sequelize.define('User', { // ... (屬性) }, { timestamps: false });
也可以只啟用 createdAt
/updatedAt
之一,并為這些列提供自定義名稱(chēng):
class Foo extends Model {} Foo.init({ /* 屬性 */ }, { sequelize, // 不要忘記啟用時(shí)間戳! timestamps: true, // 不想要 createdAt createdAt: false, // 想要 updatedAt 但是希望名稱(chēng)叫做 updateTimestamp updatedAt: 'updateTimestamp' });
2.生成模型
1.全局安裝sequelize-auto
, mysql2
npm install -g mysql2 npm install -g sequelize-auto
2. 運(yùn)行以下命令
利用sequelize-auto
對(duì)照數(shù)據(jù)庫(kù)自動(dòng)生成相應(yīng)的models,sequelize-auto
官方文檔地址:github.com/sequelize/s…
//sequelize-auto -h "數(shù)據(jù)庫(kù)地址" -d "數(shù)據(jù)庫(kù)名" -u "用戶(hù)名" -x "密碼" -p "端口號(hào)" --dialect mysql sequelize-auto -o "./model" -d test -h 127.0.0.1 -u root -p 3306 -x 123456 -e mysql Options: --help Show help [boolean] --version Show version number [boolean] -h, --host IP/Hostname for the database. [string] -d, --database Database name. [string] -u, --user Username for database. [string] -x, --pass Password for database. If specified without providing a password, it will be requested interactively from the terminal. -p, --port Port number for database (not for sqlite). Ex: MySQL/MariaDB: 3306, Postgres: 5432, MSSQL: 1433 [number] -c, --config Path to JSON file for Sequelize-Auto options and Sequelize's constructor "options" flag object as defined here: https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#instance-constructor-constructor [string] -o, --output What directory to place the models. [string] -e, --dialect The dialect/engine that you're using: postgres, mysql, sqlite, mssql [string] -a, --additional Path to JSON file containing model options (for all tables). See the options: https://sequelize.org/master/class/lib/model.js~Model.html#static-method- init [string] --indentation Number of spaces to indent [number] -t, --tables Space-separated names of tables to import [array] -T, --skipTables Space-separated names of tables to skip [array] --caseModel, --cm Set case of model names: c|l|o|p|u c = camelCase l = lower_case o = original (default) p = PascalCase u = UPPER_CASE --caseProp, --cp Set case of property names: c|l|o|p|u --caseFile, --cf Set case of file names: c|l|o|p|u|k k = kebab-case --noAlias Avoid creating alias `as` property in relations [boolean] --noInitModels Prevent writing the init-models file [boolean] -n, --noWrite Prevent writing the models to disk [boolean] -s, --schema Database schema from which to retrieve tables[string] -v, --views Include database views in generated models [boolean] -l, --lang Language for Model output: es5|es6|esm|ts es5 = ES5 CJS modules (default) es6 = ES6 CJS modules esm = ES6 ESM modules ts = TypeScript [string] --useDefine Use `sequelize.define` instead of `init` for es6|esm|ts --singularize, --sg Singularize model and file names from plural table names [boolean]
3.對(duì)應(yīng)數(shù)據(jù)庫(kù)操作符的定義
const { Op } = sequelize; [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ū)分大小寫(xiě)) (僅限 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ù)庫(kù)語(yǔ)言特定的列標(biāo)識(shí)符, 本例使用
$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
//or操作符的兩種使用 order_status=0 or order_status=1 params['$or'] = [{ order_status: 0 }, { order_status: 1 }]; params['order_status'] = { $or: [ { $eq: 0 }, { $eq: 1 } ] }
4. 增刪改查(CRUD)
1. 增加
create
向數(shù)據(jù)庫(kù)中添加單條記錄。
const User = sequelize.import('./model/user'); //導(dǎo)入模型 const user = await User.create({ username: 'alice123', isAdmin: true });
bulkCreate
批量創(chuàng)建,通過(guò)接收數(shù)組對(duì)象而不是單個(gè)對(duì)象。
await User.bulkCreate([ { username: 'foo', pwd:"123"}, { username: 'bar', pwd:"345"} ], { updateOnDuplicate: true, fields: ['username','pwd','address'] });
updateOnDuplicate
: 如果行鍵已存在是否更新。數(shù)據(jù)庫(kù)表中現(xiàn)有的記錄的唯一索引或者主鍵如果已經(jīng)存在,執(zhí)行更新操作(true表示更新,false表示不更新。 默認(rèn)為更新)
fields
: 要定義字段的數(shù)組(其余字段將被忽略),用來(lái)限制實(shí)際插入的列。
Tips:對(duì)應(yīng)原生sql語(yǔ)句講解
在MySQL數(shù)據(jù)庫(kù)中,如果在insert語(yǔ)句后面帶上ON DUPLICATE KEY UPDATE 子句。
- 要插入的行與表中現(xiàn)有記錄的惟一索引或主鍵中產(chǎn)生重復(fù)值,那么就會(huì)發(fā)生舊行的更新;
- 如果插入的行數(shù)據(jù)與現(xiàn)有表中記錄的唯一索引或者主鍵不重復(fù),則執(zhí)行新紀(jì)錄插入操作。
findOrCreate
除非找到一個(gè)滿(mǎn)足查詢(xún)參數(shù)的結(jié)果,否則方法 findOrCreate
將在表中創(chuàng)建一個(gè)條目. 在這兩種情況下,它將返回一個(gè)實(shí)例(找到的實(shí)例或創(chuàng)建的實(shí)例)和一個(gè)布爾值,指示該實(shí)例是已創(chuàng)建還是已經(jīng)存在.
使用 where
參數(shù)來(lái)查找條目,而使用 defaults
參數(shù)來(lái)定義必須創(chuàng)建的內(nèi)容. 如果 defaults
不包含每一列的值,則 Sequelize 將采用 where
的值(如果存在).
const [user, created] = await User.findOrCreate({ where: { username: '123' }, defaults: { job: 'Technical Lead JavaScript' } }); console.log(user.username); // 'sdepold' console.log(user.job); // 這可能是也可能不是 'Technical Lead JavaScript' console.log(created); // 指示此實(shí)例是否剛剛創(chuàng)建的布爾值 if (created) { console.log(user.job); // 這里肯定是 'Technical Lead JavaScript' }
2. 查詢(xún)
可選查詢(xún)參數(shù)
const result = await Goods.findAll({ attributes: [ 'goodsId', [sequelize.fn('SUM', sequelize.col('order_count')), 'order_count'], [sequelize.fn('SUM', sequelize.col('total_price_sum')), 'total_price_sum'], [sequelize.fn('SUM', sequelize.col('goods_cost')), 'goods_cost'], [sequelize.fn('COUNT', sequelize.col('goodsId')), 'goods_count'] ], where: params, limit: 10, offset:0, raw: true, group: [sequelize.col('goodsId')], })
1. attributes
如果只需要查詢(xún)模型的部分屬性,可以在通過(guò)在查詢(xún)選項(xiàng)中指定attributes
實(shí)現(xiàn),如[colName1,colName2,colName3......]
。
當(dāng)需要查詢(xún)所有字段并對(duì)某一字段使用聚合查詢(xún)時(shí),而只需要以對(duì)象的形式傳入attributes
并添加include
子屬性即可。
// 指定全查詢(xún)字段比較麻煩 Model.findAll({ attributes: ['id', 'foo', 'bar', 'baz', 'quz', [sequelize.fn('COUNT', sequelize.col('hats')), 'hats_count']] }); // 這樣會(huì)比較簡(jiǎn)短,且在你添加/刪除屬性后不會(huì)出錯(cuò) Model.findAll({ attributes: { include: [[sequelize.fn('COUNT', sequelize.col('hats')), 'hats_count']] } });
全部查詢(xún)時(shí),可以通過(guò)exclude
子屬性來(lái)排除不需要查詢(xún)的字段:
Model.findAll({ attributes: { exclude: ['baz'] } });
為列取一個(gè)別名:
在attributes
數(shù)組里面添加一項(xiàng) [ oldColName , newColName ]
或者 [ sequelize.col('oldColName') , newColName ]
通過(guò)sequelize.fn方法可以進(jìn)行聚合查詢(xún):
如常用的SUM
,COUNT
等。
2. where
在模型的 findOne
/finAll
或 update
/destroy
操作中,可以指定一個(gè)where
選項(xiàng)以指定篩選條件,where
是一個(gè)包含屬性/值對(duì)對(duì)象,sequelize會(huì)根據(jù)此對(duì)象生產(chǎn)查詢(xún)語(yǔ)句的篩選條件。
where:{ //查詢(xún) username='admin' pwd ='123456' user_status=0 or user_status=1 username: 'admin', pwd:"123456", user_status:{ [Op.or]: [ { $eq: 0 }, { $eq: 1 } ] } }
可以配合符操作來(lái)做復(fù)雜的篩選條件。
3. limit
,offset
查詢(xún)進(jìn),我們可以使用limit
限制返回結(jié)果條數(shù),并可以通過(guò)offset
來(lái)設(shè)置查詢(xún)偏移(跳過(guò))量,通過(guò)這兩個(gè)屬性我們可以實(shí)現(xiàn)分頁(yè)查詢(xún)的功能:
Model.findAll({ limit: 10 }) // 獲取 10 條數(shù)據(jù)(實(shí)例) Model.findAll({ offset: 8 }) // 跳過(guò) 8 條數(shù)據(jù)(實(shí)例) Model.findAll({ offset: 5, limit: 5 }) // 跳過(guò) 5 條數(shù)據(jù)并獲取其后的 5 條數(shù)據(jù)(實(shí)例) //使用場(chǎng)景,分頁(yè)請(qǐng)求數(shù)據(jù) const page = parseInt(params.page || 1); const limit = parseInt(params.limit || 10); const currentPage = (page - 1) * limit; Model.findAll({ limit, offset: currentPage, })
4. raw
{ raw: true }
作為參數(shù)傳遞給 finder時(shí),可以對(duì)查詢(xún)的結(jié)果集禁用包裝。
5. order
order
參數(shù)采用一系列 項(xiàng) 來(lái)讓 sequelize 方法對(duì)查詢(xún)進(jìn)行排序. 這些 項(xiàng) 本身是 [column, direction]
形式的數(shù)組. 該列將被正確轉(zhuǎn)義,并且將在有效方向列表中進(jìn)行驗(yàn)證(例如 ASC
, DESC
, NULLS FIRST
等).
Model.findAll({ order: [ //sequelize.col('date') 有時(shí)候可以使用sequelize.col()指定列,防止在子查詢(xún)或者關(guān)聯(lián)查詢(xún)時(shí)找不到列名 [sequelize.col('date'), 'DESC'], ['date', 'DESC'], // 將轉(zhuǎn)義 title 并針對(duì)有效方向列表進(jìn)行降序排列 ['title', 'DESC'], // 將按最大年齡進(jìn)行升序排序 sequelize.fn('max', sequelize.col('age')), // 將按最大年齡進(jìn)行降序排序 [sequelize.fn('max', sequelize.col('age')), 'DESC'], // 將按 otherfunction(`col1`, 12, 'lalala') 進(jìn)行降序排序 [sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'], // 將使用模型名稱(chēng)作為關(guān)聯(lián)名稱(chēng)按關(guān)聯(lián)模型的 createdAt 排序. [Task, 'createdAt', 'DESC'], // 將使用模型名稱(chēng)作為關(guān)聯(lián)名稱(chēng)通過(guò)關(guān)聯(lián)模型的 createdAt 排序. [Task, Project, 'createdAt', 'DESC'], // 將使用關(guān)聯(lián)名稱(chēng)按關(guān)聯(lián)模型的 createdAt 排序. ['Task', 'createdAt', 'DESC'], // 將使用關(guān)聯(lián)的名稱(chēng)按嵌套的關(guān)聯(lián)模型的 createdAt 排序. ['Task', 'Project', 'createdAt', 'DESC'], // 將使用關(guān)聯(lián)對(duì)象按關(guān)聯(lián)模型的 createdAt 排序. (首選方法) [Subtask.associations.Task, 'createdAt', 'DESC'], // 將使用關(guān)聯(lián)對(duì)象按嵌套關(guān)聯(lián)模型的 createdAt 排序. (首選方法) [Subtask.associations.Task, Task.associations.Project, 'createdAt', 'DESC'], // 將使用簡(jiǎn)單的關(guān)聯(lián)對(duì)象按關(guān)聯(lián)模型的 createdAt 排序. [{model: Task, as: 'Task'}, 'createdAt', 'DESC'], // 將由嵌套關(guān)聯(lián)模型的 createdAt 簡(jiǎn)單關(guān)聯(lián)對(duì)象排序. [{model: Task, as: 'Task'}, {model: Project, as: 'Project'}, 'createdAt', 'DESC'] ], // 將按最大年齡降序排列 order: sequelize.literal('max(age) DESC'), // 如果忽略方向,則默認(rèn)升序,將按最大年齡升序排序 order: sequelize.fn('max', sequelize.col('age')), // 如果省略方向,則默認(rèn)升序, 將按年齡升序排列 order: sequelize.col('age'), // 將根據(jù)方言隨機(jī)排序(但不是 fn('RAND') 或 fn('RANDOM')) order: sequelize.random() }); Model.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, 這種嵌套可能是無(wú)限的! [sequelize.fn('otherfunction', sequelize.fn('awesomefunction', sequelize.col('col'))), 'DESC'] ] });
order
數(shù)組的元素可以如下:
一個(gè)字符串 (它將被自動(dòng)引用)
一個(gè)數(shù)組, 其第一個(gè)元素將被引用,第二個(gè)將被逐字追加
一個(gè)具有raw
字段的對(duì)象:
raw
內(nèi)容將不加引用地逐字添加- 其他所有內(nèi)容都將被忽略,如果未設(shè)置
raw
,查詢(xún)將失敗
調(diào)用 Sequelize.fn
(這將在 SQL 中生成一個(gè)函數(shù)調(diào)用)
調(diào)用 Sequelize.col
(這將引用列名)
6. group
分組和排序的語(yǔ)法相同,只是分組不接受方向作為數(shù)組的最后一個(gè)參數(shù)(不存在 ASC
, DESC
, NULLS FIRST
等).
還可以將字符串直接傳遞給 group
,該字符串將直接(普通)包含在生成的 SQL 中.
Model.findAll({ group: 'name' }); Model.findAll({ group: [sequelize.col('date'),sequelize.col('id')] //可以指定多個(gè)列進(jìn)行分組 }); // 生成 'GROUP BY name'
Tips:在做分組和排序的時(shí)候可以使用sequelize.col()指定列,防止在子查詢(xún)或者關(guān)聯(lián)查詢(xún)時(shí)找不到列名
7. include
include
關(guān)鍵字表示關(guān)聯(lián)查詢(xún)
簡(jiǎn)單查詢(xún)
1. findOne
findOne
方法獲得它找到的第一個(gè)條目(它可以滿(mǎn)足提供的可選查詢(xún)參數(shù)).
const user = await User.findOne({ where: { username: 'admin' } });
2.findAll
該查詢(xún)將從表中檢索所有條目(除非受到 where
子句的限制).
const user = await User.findAll({ where: { username: 'admin' },raw:true });
3.findAndCountAll,findAndCount
findAndCountAll
方法是結(jié)合了 findAll
和 count
的便捷方法. 在處理與分頁(yè)有關(guān)的查詢(xún)時(shí)非常有用,在分頁(yè)中,你想檢索帶有 limit
和 offset
的數(shù)據(jù),但又需要知道與查詢(xún)匹配的記錄總數(shù).
當(dāng)沒(méi)有提供 group
時(shí), findAndCountAll
方法返回一個(gè)具有兩個(gè)屬性的對(duì)象:
count
: 一個(gè)整數(shù) - 與查詢(xún)匹配的記錄總數(shù)rows
:一個(gè)數(shù)組對(duì)象 - 獲得的記錄
當(dāng)提供了 group
時(shí), findAndCountAll
方法返回一個(gè)具有兩個(gè)屬性的對(duì)象:
count
- 一個(gè)數(shù)組對(duì)象 - 包含每組中的合計(jì)和預(yù)設(shè)屬性rows
- 一個(gè)數(shù)組對(duì)象 - 獲得的記錄
const { count, rows } = await User.findAndCountAll({ where: { username: { [Op.like]: '%foo%' } }, offset: 10, //查詢(xún)偏移(跳過(guò))量 limit: 2 //限制返回結(jié)果條數(shù) });
關(guān)聯(lián)查詢(xún)
let result = await Goods.findAndCount({ include: [ { attributes: [[sequelize.col('title'), 'goods_name']], association: Goods.belongsTo(tbGoods, { targetKey: 'goodsId', foreignKey: 'goodsId' , as:'goods_name_info'}), model: Goods, required: false, where: params2, } ], where: params, limit, offset: currentPage, raw: true, order: [ [sequelize.col('date'), 'DESC'], ] })
關(guān)聯(lián)類(lèi)型
A.hasOne(B, { /* 參數(shù) */ }); // A 有一個(gè) B A.belongsTo(B, { /* 參數(shù) */ }); // A 屬于 B A.hasMany(B, { /* 參數(shù) */ }); // A 有多個(gè) B A.belongsToMany(B, { through: 'C', /* 參數(shù) */ }); // A 屬于多個(gè) B , 通過(guò)聯(lián)結(jié)表 C
association
as
指定連接的別名
where
關(guān)聯(lián)中也支持where子句。
required
false,表示左外連接(LEFT OUTER JOIN),左表全部出現(xiàn)在結(jié)果集中,若右表無(wú)對(duì)應(yīng)記錄,則相應(yīng)字段為NULL
。
true,表示內(nèi)連接(INNER JOIN),滿(mǎn)足條件的記錄才會(huì)出現(xiàn)在結(jié)果集中。
子查詢(xún)
Tips:由于 sequelize.literal
會(huì)插入任意內(nèi)容而不進(jìn)行轉(zhuǎn)義
//根據(jù)goodsId 去匹配 goods_order對(duì)應(yīng)的 goods_name let result = await goods_roi.findAll({ attributes: [ 'goodsId', [sequelize.fn('SUM', sequelize.col('order_count')), 'order_count'], [sequelize.fn('SUM', sequelize.col('total_price_sum')), 'total_price_sum'], [sequelize.fn('SUM', sequelize.col('goods_cost')), 'goods_cost'], [ sequelize.literal(`( SELECT item_title FROM goods_order AS goods_order WHERE goods_order.item_id = goods_roi.goodsId limit 1 )`), 'goods_name' ] ], where: params, raw: true, group: [sequelize.col('goodsId')] })
實(shí)用方法 count
,max
,min
,sum
,increment
, decrement
count
方法僅計(jì)算數(shù)據(jù)庫(kù)中元素出現(xiàn)的次數(shù)
const amount = await Model.count({ where: { id: { [Op.gt]: 25 } } }); console.log(`這有 ${amount} 個(gè)記錄 id 大于 25`);
max
, min
和 sum
假設(shè)我們有三個(gè)用戶(hù),分別是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
increment自增, decrement自減
await User.increment({age: 5}, { where: { id: 1 } }) // 將年齡增加到15歲 await User.increment({age: -5}, { where: { id: 1 } }) // 將年齡降至5歲
3. 更新 update
update查詢(xún)也接受 where
參數(shù)
*// 將所有沒(méi)有姓氏的人更改為 "Doe"* await User.update({ lastName: "Doe" }, { where: { lastName: null } });
4. 刪除 destroy
destroy查詢(xún)也接受 where
參數(shù)
*// 刪除所有名為 "Jane" 的人* await User.destroy({ where: { firstName: "Jane" } });
5. 托管事務(wù)(transaction)
Sequelize 支持兩種使用事務(wù)的方式:
- 托管事務(wù): 如果引發(fā)任何錯(cuò)誤,Sequelize 將自動(dòng)回滾事務(wù),否則將提交事務(wù). 另外,如果啟用了CLS(連續(xù)本地存儲(chǔ)),則事務(wù)回調(diào)中的所有查詢(xún)將自動(dòng)接收事務(wù)對(duì)象.
- 非托管事務(wù): 提交和回滾事務(wù)應(yīng)由用戶(hù)手動(dòng)完成(通過(guò)調(diào)用適當(dāng)?shù)?Sequelize 方法).
托管事務(wù)會(huì)自動(dòng)處理提交或回滾事務(wù). 通過(guò)將回調(diào)傳遞給 sequelize.transaction
來(lái)啟動(dòng)托管事務(wù). 這個(gè)回調(diào)可以是 async
(通常是)的.
在這種情況下,將發(fā)生以下情況:
- Sequelize 將自動(dòng)開(kāi)始事務(wù)并獲得事務(wù)對(duì)象
t
- 然后,Sequelize 將執(zhí)行你提供的回調(diào),并在其中傳遞
t
- 如果你的回調(diào)拋出錯(cuò)誤,Sequelize 將自動(dòng)回滾事務(wù)
- 如果你的回調(diào)成功,Sequelize 將自動(dòng)提交事務(wù)
只有這樣,sequelize.transaction
調(diào)用才會(huì)解決:
- 解決你的回調(diào)的決議
- 或者,如果你的回調(diào)引發(fā)錯(cuò)誤,則拒絕并拋出錯(cuò)誤
try { const result = await sequelize.transaction(async (t) => { const user = await User.create({ firstName: 'Abraham', lastName: 'Lincoln' }, { transaction: t }); //{transaction: t} 必須作為第二個(gè)對(duì)象里的參數(shù)傳遞 return user; }); // 如果執(zhí)行到此行,則表示事務(wù)已成功提交,`result`是事務(wù)返回的結(jié)果 // `result` 就是從事務(wù)回調(diào)中返回的結(jié)果(在這種情況下為 `user`) } catch (error) { // 如果執(zhí)行到此,則發(fā)生錯(cuò)誤. // 該事務(wù)已由 Sequelize 自動(dòng)回滾! }
注意:t.commit()
和 t.rollback()
沒(méi)有被直接調(diào)用.
自動(dòng)將事務(wù)傳遞給所有查詢(xún):在上面的示例中,仍然通過(guò)傳遞 { transaction: t }
作為第二個(gè)參數(shù)來(lái)手動(dòng)傳遞事務(wù).
以上為js版本,部分不適用于ts,ts要根據(jù)具體的官方文檔使用。
以上就是Nodejs Sequelize手冊(cè)學(xué)習(xí)快速入門(mén)到應(yīng)用的詳細(xì)內(nèi)容,更多關(guān)于Nodejs Sequelize入門(mén)手冊(cè)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
NodeJS實(shí)現(xiàn)一個(gè)聊天室功能
這篇文章主要介紹了NodeJS實(shí)現(xiàn)一個(gè)聊天室功能,本文實(shí)例截圖相結(jié)合給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-11-11Koa2微信公眾號(hào)開(kāi)發(fā)之消息管理
這篇文章主要介紹了Koa2微信公眾號(hào)開(kāi)發(fā)之消息管理,這一節(jié)我們就來(lái)看看公眾號(hào)的消息管理。并實(shí)現(xiàn)一個(gè)自動(dòng)回復(fù)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05node.js中http模塊和url模塊的簡(jiǎn)單介紹
這篇文章主要給大家簡(jiǎn)單介紹了關(guān)于node.js中的http模塊和url模塊,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用node.js具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-10-10Node.js中MongoDB插入數(shù)據(jù)的實(shí)現(xiàn)方法
在Node.js中,可以使用MongoDB原生驅(qū)動(dòng)或Mongoose庫(kù)來(lái)連接和操作MongoDB數(shù)據(jù)庫(kù),本文就來(lái)介紹一下Node.js中MongoDB插入數(shù)據(jù)的實(shí)現(xiàn)方法,感興趣的可以了解一下2023-12-12Node.js實(shí)現(xiàn)登錄注冊(cè)功能
這篇文章主要為大家詳細(xì)介紹了Node.js實(shí)現(xiàn)登錄注冊(cè)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04node.js入門(mén)學(xué)習(xí)之url模塊
最近在學(xué)習(xí)nodejs,知道了如何用nodejs創(chuàng)建一個(gè)簡(jiǎn)單的小項(xiàng)目。例如如何創(chuàng)建一個(gè)服務(wù)器啦,例如http.createServer,還有根據(jù)不同的請(qǐng)求路徑來(lái)設(shè)置路由選擇啦,模塊引入,創(chuàng)建模塊啦,下面這篇文章主要介紹了node.js中url模塊的相關(guān)資料,需要的朋友可以參考下。2017-02-02node.js中的buffer.toString方法使用說(shuō)明
這篇文章主要介紹了node.js中的buffer.toString方法使用說(shuō)明,本文介紹了buffer.toString的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12