此係列文章的應用示例已發佈於 GitHub: sequelize-docs-Zh-CN. 能夠 Fork 幫助改進或 Star 關注更新. 歡迎 Star.html
Finder 方法旨在從數據庫查詢數據。 他們 不 返回簡單的對象,而是返回模型實例。 由於 finder 方法返回模型實例,您能夠按照 實例 的文檔中所述,爲結果調用任何模型實例成員。git
在本文中,咱們將探討 finder 方法能夠作什麼:github
find
- 搜索數據庫中的一個特定元素// 搜索已知的ids Project.findById(123).then(project => { // project 將是 Project的一個實例,並具備在表中存爲 id 123 條目的內容。 // 若是沒有定義這樣的條目,你將得到null }) // 搜索屬性 Project.findOne({ where: {title: 'aProject'} }).then(project => { // project 將是 Projects 表中 title 爲 'aProject' 的第一個條目 || null }) Project.findOne({ where: {title: 'aProject'}, attributes: ['id', ['name', 'title']] }).then(project => { // project 將是 Projects 表中 title 爲 'aProject' 的第一個條目 || null // project.title 將包含 project 的 name })
findOrCreate
- 搜索特定元素或建立它(若是不可用)方法 findOrCreate
可用於檢查數據庫中是否已存在某個元素。 若是是這種狀況,則該方法將生成相應的實例。 若是元素不存在,將會被建立。sql
若是是這種狀況,則該方法將致使相應的實例。 若是元素不存在,將會被建立。數據庫
假設咱們有一個空的數據庫,一個 User
模型有一個 username
和 job
。數組
User .findOrCreate({where: {username: 'sdepold'}, defaults: {job: 'Technical Lead JavaScript'}}) .spread((user, created) => { console.log(user.get({ plain: true })) console.log(created) /* findOrCreate 返回一個包含已找到或建立的對象的數組,找到或建立的對象和一個布爾值,若是建立一個新對象將爲true,不然爲false,像這樣: [ { username: 'sdepold', job: 'Technical Lead JavaScript', id: 1, createdAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET), updatedAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET) }, true ] 在上面的例子中,".spread" 將數組分紅2部分,並將它們做爲參數傳遞給回調函數,在這種狀況下將它們視爲 "user" 和 "created" 。(因此「user」將是返回數組的索引0的對象,而且 "created" 將等於 "true"。) */ })
代碼建立了一個新的實例。 因此當咱們已經有一個實例了 ...函數
User.create({ username: 'fnord', job: 'omnomnom' }) .then(() => User.findOrCreate({where: {username: 'fnord'}, defaults: {job: 'something else'}})) .spread((user, created) => { console.log(user.get({ plain: true })) console.log(created) /* 在這個例子中,findOrCreate 返回一個以下的數組: [ { username: 'fnord', job: 'omnomnom', id: 2, createdAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET), updatedAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET) }, false ] 由findOrCreate返回的數組經過 ".spread" 擴展爲兩部分,而且這些部分將做爲2個參數傳遞給回調函數,在這種狀況下將其視爲 "user" 和 "created" 。(因此「user」將是返回數組的索引0的對象,而且 "created" 將等於 "false"。) */ })
...現有條目將不會更改。 看到第二個用戶的 "job",而且實際上建立操做是假的。ui
findAndCountAll
- 在數據庫中搜索多個元素,返回數據和總計數這是一個方便的方法,它結合了 findAll
和 count
(見下文),當處理與分頁相關的查詢時,這是有用的,你想用 limit
和 offset
檢索數據,但也須要知道總數與查詢匹配的記錄數:code
處理程序成功將始終接收具備兩個屬性的對象:htm
count
- 一個整數,總數記錄匹配where語句rows
- 一個數組對象,記錄在limit和offset範圍內匹配where語句,Project .findAndCountAll({ where: { title: { [Op.like]: 'foo%' } }, offset: 10, limit: 2 }) .then(result => { console.log(result.count); console.log(result.rows); });
findAndCountAll
也支持 include。 只有標記爲 required
的 include 將被添加到計數部分:
假設您想查找附有我的資料的全部用戶:
User.findAndCountAll({ include: [ { model: Profile, required: true} ], limit: 3 });
由於 Profile
的 include 有 required
設置,這將致使內部鏈接,而且只有具備 profile 的用戶將被計數。 若是咱們從 include 中刪除required
,那麼有和沒有 profile 的用戶都將被計數。 在include中添加一個 where
語句會自動使它成爲 required:
User.findAndCountAll({ include: [ { model: Profile, where: { active: true }} ], limit: 3 });
上面的查詢只會對具備 active profile 的用戶進行計數,由於在將 where 語句添加到 include 時,required
被隱式設置爲 true。
傳遞給 findAndCountAll
的 options 對象與 findAll
相同(以下所述)。
findAll
- 搜索數據庫中的多個元素// 找到多個條目 Project.findAll().then(projects => { // projects 將是全部 Project 實例的數組 }) // 也能夠: Project.all().then(projects => { // projects 將是全部 Project 實例的數組 }) // 搜索特定屬性 - 使用哈希 Project.findAll({ where: { name: 'A Project' } }).then(projects => { // projects將是一個具備指定 name 的 Project 實例數組 }) // 在特定範圍內進行搜索 Project.findAll({ where: { id: [1,2,3] } }).then(projects => { // projects將是一系列具備 id 1,2 或 3 的項目 // 這其實是在作一個 IN 查詢 }) Project.findAll({ where: { id: { [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.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' (不區分大小寫) (僅限 PG) [Op.notILike]: '%hat', // 不包含 '%hat' (僅限 PG) [Op.overlap]: [1, 2], // && [1, 2] (PG數組重疊運算符) [Op.contains]: [1, 2], // @> [1, 2] (PG數組包含運算符) [Op.contained]: [1, 2], // <@ [1, 2] (PG數組包含於運算符) [Op.any]: [2,3], // 任何數組[2, 3]::INTEGER (僅限 PG) }, status: { [Op.not]: false, // status 不爲 FALSE } } })
你可使用多層嵌套的 AND,OR 和 NOT 條件進行一個複合的 where 查詢。 爲了作到這一點,你可使用 or
, and
或 not
運算符
:
Project.findOne({ where: { name: 'a project', [Op.or]: [ { id: [1,2,3] }, { id: { [Op.gt]: 10 } } ] } }) Project.findOne({ where: { name: 'a project', id: { [Op.or]: [ [1,2,3], { [Op.gt]: 10 } ] } } })
這兩段代碼將生成如下內容:
SELECT * FROM `Projects` WHERE ( `Projects`.`name` = 'a project' AND (`Projects`.`id` IN (1,2,3) OR `Projects`.`id` > 10) ) LIMIT 1;
not
示例:
Project.findOne({ where: { name: 'a project', [Op.not]: [ { id: [1,2,3] }, { array: { [Op.contains]: [3,4,5] } } ] } });
將生成:
SELECT * FROM `Projects` WHERE ( `Projects`.`name` = 'a project' AND NOT (`Projects`.`id` IN (1,2,3) OR `Projects`.`array` @> ARRAY[3,4,5]::INTEGER[]) ) LIMIT 1;
要獲取更多相關數據,可使用限制,偏移,順序和分組:
// 限制查詢的結果 Project.findAll({ limit: 10 }) // 跳過前10個元素 Project.findAll({ offset: 10 }) // 跳過前10個元素,並獲取2個 Project.findAll({ offset: 10, limit: 2 })
分組和排序的語法是相同的,因此下面只用一個單獨的例子來解釋分組,而其他的則是排序。 您下面看到的全部內容也能夠對分組進行
Project.findAll({order: 'title DESC'}) // 生成 ORDER BY title DESC Project.findAll({group: 'name'}) // 生成 GROUP BY name
請注意,在上述兩個示例中,提供的字符串逐字插入到查詢中,因此不會轉義列名稱。 當你向 order / group 提供字符串時,將始終如此。 若是要轉義列名,您應該提供一個參數數組,即便您只想經過單個列進行 order / group
something.findOne({ order: [ 'name', // 將返回 `name` 'username DESC', // 將返回 `username DESC` -- 不要這樣作 ['username', 'DESC'], // 將返回 `username` DESC sequelize.fn('max', sequelize.col('age')), // 將返回 max(`age`) [sequelize.fn('max', sequelize.col('age')), 'DESC'], // 將返回 max(`age`) DESC [sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'], // 將返回 otherfunction(`col1`, 12, 'lalala') DESC [sequelize.fn('otherfunction', sequelize.fn('awesomefunction', sequelize.col('col'))), 'DESC'] // 將返回 otherfunction(awesomefunction(`col`)) DESC,這個嵌套是能夠無限的! ] })
回顧一下,order / group數組的元素能夠是如下內容:
Object -
有時候,你可能會期待一個你想要顯示的大量數據集,而無需操做。 對於你選擇的每一行,Sequelize 建立一個具備更新,刪除和獲取關聯等功能的實例。若是您有數千行,則可能須要一些時間。 若是您只須要原始數據,而且不想更新任何內容,您能夠這樣作來獲取原始數據。
// 你指望從數據庫的一個巨大的數據集, // 而且不想花時間爲每一個條目構建DAO? // 您能夠傳遞一個額外的查詢參數來取代原始數據: Project.findAll({ where: { ... }, raw: true })
count
- 計算數據庫中元素的出現次數還有一種數據庫對象計數的方法:
Project.count().then(c => { console.log("There are " + c + " projects!") }) Project.count({ where: {'id': {[Op.gt]: 25}} }).then(c => { console.log("There are " + c + " projects with an id greater than 25.") })
max
- 獲取特定表中特定屬性的最大值這裏是獲取屬性的最大值的方法:
/* 咱們假設3個具備屬性年齡的對象。 第一個是10歲, 第二個是5歲, 第三個是40歲。 */ Project.max('age').then(max => { // 將返回 40 }) Project.max('age', { where: { age: { [Op.lt]: 20 } } }).then(max => { // 將會是 10 })
min
- 獲取特定表中特定屬性的最小值這裏是獲取屬性的最小值的方法:
/* 咱們假設3個具備屬性年齡的對象。 第一個是10歲, 第二個是5歲, 第三個是40歲。 */ Project.min('age').then(min => { // 將返回 5 }) Project.min('age', { where: { age: { [Op.gt]: 5 } } }).then(min => { // 將會是 10 })
sum
- 特定屬性的值求和爲了計算表的特定列的總和,可使用「sum」方法。
/* 咱們假設3個具備屬性年齡的對象。 第一個是10歲, 第二個是5歲, 第三個是40歲。 */ Project.sum('age').then(sum => { // 將返回 55 }) Project.sum('age', { where: { age: { [Op.gt]: 5 } } }).then(sum => { // 將會是 50 })
當你從數據庫檢索數據時,也想同時得到與之相關聯的查詢,這被稱爲預加載。這個基本思路就是當你調用 find
或 findAll
時使用 include
屬性。讓咱們假設如下設置:
const User = sequelize.define('user', { name: Sequelize.STRING }) const Task = sequelize.define('task', { name: Sequelize.STRING }) const Tool = sequelize.define('tool', { name: Sequelize.STRING }) Task.belongsTo(User) User.hasMany(Task) User.hasMany(Tool, { as: 'Instruments' }) sequelize.sync().then(() => { // 這是咱們繼續的地方 ... })
首先,讓咱們用它們的關聯 user 加載全部的 task。
Task.findAll({ include: [ User ] }).then(tasks => { console.log(JSON.stringify(tasks)) /* [{ "name": "A Task", "id": 1, "createdAt": "2013-03-20T20:31:40.000Z", "updatedAt": "2013-03-20T20:31:40.000Z", "userId": 1, "user": { "name": "John Doe", "id": 1, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z" } }] */ })
請注意,訪問者(結果實例中的 User
屬性)是單數形式,由於關聯是一對一的。
接下來的事情:用多對一的關聯加載數據!
User.findAll({ include: [ Task ] }).then(users => { console.log(JSON.stringify(users)) /* [{ "name": "John Doe", "id": 1, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "tasks": [{ "name": "A Task", "id": 1, "createdAt": "2013-03-20T20:31:40.000Z", "updatedAt": "2013-03-20T20:31:40.000Z", "userId": 1 }] }] */ })
請注意,訪問者(結果實例中的 Tasks
屬性)是複數形式,由於關聯是多對一的。
若是關聯是別名的(使用 as
參數),則在包含模型時必須指定此別名。 注意用戶的 Tool
如何被別名爲 Instruments
。 爲了得到正確的權限,您必須指定要加載的模型以及別名:
User.findAll({ include: [{ model: Tool, as: 'Instruments' }] }).then(users => { console.log(JSON.stringify(users)) /* [{ "name": "John Doe", "id": 1, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "Instruments": [{ "name": "Toothpick", "id": 1, "createdAt": null, "updatedAt": null, "userId": 1 }] }] */ })
您還能夠經過指定與關聯別名匹配的字符串來包含別名:
User.findAll({ include: ['Instruments'] }).then(users => { console.log(JSON.stringify(users)) /* [{ "name": "John Doe", "id": 1, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "Instruments": [{ "name": "Toothpick", "id": 1, "createdAt": null, "updatedAt": null, "userId": 1 }] }] */ }) User.findAll({ include: [{ association: 'Instruments' }] }).then(users => { console.log(JSON.stringify(users)) /* [{ "name": "John Doe", "id": 1, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "Instruments": [{ "name": "Toothpick", "id": 1, "createdAt": null, "updatedAt": null, "userId": 1 }] }] */ })
當預加載時,咱們也可使用 where
過濾關聯的模型。 這將返回 Tool
模型中全部與 where
語句匹配的行的User
。
User.findAll({ include: [{ model: Tool, as: 'Instruments', where: { name: { [Op.like]: '%ooth%' } } }] }).then(users => { console.log(JSON.stringify(users)) /* [{ "name": "John Doe", "id": 1, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "Instruments": [{ "name": "Toothpick", "id": 1, "createdAt": null, "updatedAt": null, "userId": 1 }] }], [{ "name": "John Smith", "id": 2, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "Instruments": [{ "name": "Toothpick", "id": 1, "createdAt": null, "updatedAt": null, "userId": 1 }] }], */ })
當使用 include.where
過濾一個預加載的模型時,include.required
被隱式設置爲 true
。 這意味着內部聯接完成返回具備任何匹配子項的父模型。
將模型的 WHERE
條件從 ON
條件的 include 模式移動到頂層,你可使用 '$nested.column$'
語法:
User.findAll({ where: { '$Instruments.name$': { [Op.iLike]: '%ooth%' } }, include: [{ model: Tool, as: 'Instruments' }] }).then(users => { console.log(JSON.stringify(users)); /* [{ "name": "John Doe", "id": 1, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "Instruments": [{ "name": "Toothpick", "id": 1, "createdAt": null, "updatedAt": null, "userId": 1 }] }], [{ "name": "John Smith", "id": 2, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "Instruments": [{ "name": "Toothpick", "id": 1, "createdAt": null, "updatedAt": null, "userId": 1 }] }], */
要包含全部屬性,您可使用 all:true
傳遞單個對象:
User.findAll({ include: [{ all: true }]});
若是想要加載軟刪除的記錄,能夠經過將 include.paranoid
設置爲 false
來實現
User.findAll({ include: [{ model: Tool, where: { name: { [Op.like]: '%ooth%' } }, paranoid: false // query and loads the soft deleted records }] });
在一對多關係的狀況下。
Company.findAll({ include: [ Division ], order: [ [ Division, 'name' ] ] }); Company.findAll({ include: [ Division ], order: [ [ Division, 'name', 'DESC' ] ] }); Company.findAll({ include: [ { model: Division, as: 'Div' } ], order: [ [ { model: Division, as: 'Div' }, 'name' ] ] }); Company.findAll({ include: [ { model: Division, as: 'Div' } ], order: [ [ { model: Division, as: 'Div' }, 'name', 'DESC' ] ] }); Company.findAll({ include: [ { model: Division, include: [ Department ] } ], order: [ [ Division, Department, 'name' ] ] });
在多對多關係的狀況下,您還能夠經過表中的屬性進行排序。
Company.findAll({ include: [ { model: Division, include: [ Department ] } ], order: [ [ Division, DepartmentDivision, 'name' ] ] });
您可使用嵌套的預加載來加載相關模型的全部相關模型:
User.findAll({ include: [ {model: Tool, as: 'Instruments', include: [ {model: Teacher, include: [ /* etc */]} ]} ] }).then(users => { console.log(JSON.stringify(users)) /* [{ "name": "John Doe", "id": 1, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "Instruments": [{ // 1:M and N:M association "name": "Toothpick", "id": 1, "createdAt": null, "updatedAt": null, "userId": 1, "Teacher": { // 1:1 association "name": "Jimi Hendrix" } }] }] */ })
這將產生一個外鏈接。 可是,相關模型上的 where
語句將建立一個內部鏈接,並僅返回具備匹配子模型的實例。 要返回全部父實例,您應該添加 required: false
。
User.findAll({ include: [{ model: Tool, as: 'Instruments', include: [{ model: Teacher, where: { school: "Woodstock Music School" }, required: false }] }] }).then(users => { /* ... */ })
以上查詢將返回全部用戶及其全部樂器,但只會返回與 Woodstock Music School
相關的老師。
包括全部也支持嵌套加載:
User.findAll({ include: [{ all: true, nested: true }]});
若是這篇文章對您有幫助, 感謝 下方點贊 或 Star GitHub: sequelize-docs-Zh-CN 支持, 謝謝.