此係列文章的應用示例已發佈於 GitHub: sequelize-docs-Zh-CN. 能夠 Fork 幫助改進或 Star 關注更新. 歡迎 Star.html
做用域容許你定義經常使用查詢,以便之後輕鬆使用。 做用域能夠包括與常規查找器 where
, include
, limit
等全部相同的屬性。git
做用域在模型定義中定義,能夠是finder對象或返回finder對象的函數,除了默認做用域,該做用於只能是一個對象:程序員
const Project = sequelize.define('project', { // 屬性 }, { defaultScope: { where: { active: true } }, scopes: { deleted: { where: { deleted: true } }, activeUsers: { include: [ { model: User, where: { active: true }} ] }, random: function () { return { where: { someNumber: Math.random() } } }, accessLevel: function (value) { return { where: { accessLevel: { [Op.gte]: value } } } } } });
經過調用 addScope
定義模型後,還能夠添加做用域。 這對於具備包含的做用域特別有用,其中在定義其餘模型時可能不會定義 include 中的模型。github
始終應用默認做用域。 這意味着,經過上面的模型定義,Project.findAll()
將建立如下查詢:sql
SELECT * FROM projects WHERE active = true
能夠經過調用 .unscoped()
, .scope(null)
或經過調用另外一個做用域來刪除默認做用域:數組
Project.scope('deleted').findAll(); // 刪除默認做用域
SELECT * FROM projects WHERE deleted = true
還能夠在做用域定義中包含做用域模型。 這讓你避免重複 include
,attributes
或 where
定義。dom
使用上面的例子,並在包含的用戶模型中調用 active
做用域(而不是直接在該 include 對象中指定條件):函數
activeUsers: { include: [ { model: User.scope('active')} ] }
經過在模型定義上調用 .scope
來應用做用域,傳遞一個或多個做用域的名稱。 .scope
返回一個全功能的模型實例,它具備全部常規的方法:.findAll
,.update
,.count
,.destroy
等等。你能夠保存這個模型實例並稍後再次使用:post
const DeletedProjects = Project.scope('deleted'); DeletedProjects.findAll(); // 過一段時間 // 讓咱們再次尋找被刪除的項目! DeletedProjects.findAll();
做用域適用於 .find
, .findAll
, .count
, .update
和 .destroy
.this
能夠經過兩種方式調用做爲函數的做用域。 若是做用域沒有任何參數,它能夠正常調用。 若是做用域採用參數,則傳遞一個對象:
Project.scope('random', { method: ['accessLevel', 19]}).findAll();
SELECT * FROM projects WHERE someNumber = 42 AND accessLevel >= 19
經過將做用域數組傳遞到 .scope
或經過將做用域做爲連續參數傳遞,能夠同時應用多個做用域。
// 這兩個是等價的 Project.scope('deleted', 'activeUsers').findAll(); Project.scope(['deleted', 'activeUsers']).findAll();
SELECT * FROM projects INNER JOIN users ON projects.userId = users.id AND users.active = true
若是要將其餘做用域與默認做用域一塊兒應用,請將鍵 defaultScope
傳遞給 .scope
:
Project.scope('defaultScope', 'deleted').findAll();
SELECT * FROM projects WHERE active = true AND deleted = true
當調用多個做用域時,後續做用域的鍵將覆蓋之前的做用域(相似於 _.assign )。 考慮兩個做用域:
{ scope1: { where: { firstName: 'bob', age: { [Op.gt]: 20 } }, limit: 2 }, scope2: { where: { age: { [Op.gt]: 30 } }, limit: 10 } }
調用 .scope('scope1', 'scope2')
將產生如下查詢
WHERE firstName = 'bob' AND age > 30 LIMIT 10
注意 scope2
覆蓋 limit
和 age
,而 firstName
被保留。 limit
,offset
,order
,paranoid
,lock
和raw
被覆蓋,而where
和include
被淺層合併。 這意味着相同的鍵在同一個模型的對象以及隨後的包含都將相互覆蓋。
當將查找對象直接傳遞到做用域模型上的 findAll 時,適用相同的合併邏輯:
Project.scope('deleted').findAll({ where: { firstName: 'john' } })
WHERE deleted = true AND firstName = 'john'
這裏的 deleted
做用域與 finder 合併。 若是咱們要將 where: { firstName: 'john', deleted: false }
傳遞給 finder,那麼 deleted
做用域將被覆蓋。
Sequelize 與關聯有兩個不一樣但相關的做用域概念。 差別是微妙但重要的:
get
,set
,add
和create
相關聯的模型函數時,這個做用域僅在兩個模型之間的關聯上被調用舉個例子,思考模型Post和Comment。 註釋與其餘幾個模型(圖像,視頻等)相關聯,註釋和其餘模型之間的關聯是多態的,這意味着除了外鍵 commentable_id
以外,註釋還存儲一個commentable
列。
可使用 association scope 來實現多態關聯:
this.Post.hasMany(this.Comment, { foreignKey: 'commentable_id', scope: { commentable: 'post' } });
當調用 post.getComments()
時,這將自動添加 WHERE commentable = 'post'
。 相似地,當向帖子添加新的註釋時,commentable
會自動設置爲 'post'
。 關聯做用域是爲了存活於後臺,沒有程序員沒必要擔憂 - 它不能被禁用。 有關更完整的多態性示例,請參閱 關聯做用域
那麼考慮那個Post的默認做用域只顯示活動的帖子:where: { active: true }
。 該做用域存在於相關聯的模型(Post)上,而不是像commentable
做用域那樣在關聯上。 就像在調用Post.findAll()
時同樣應用默認做用域,當調用 User.getPosts()
時,它也會被應用 - 這隻會返回該用戶的活動帖子。
要禁用默認做用域,將 scope: null
傳遞給 getter: User.getPosts({ scope: null })
。 一樣,若是要應用其餘做用域,請像這樣:
User.getPosts({ scope: ['scope1', 'scope2']});
若是要爲關聯模型上的做用域建立快捷方式,能夠將做用域模型傳遞給關聯。 考慮一個快捷方式來獲取用戶全部已刪除的帖子:
const Post = sequelize.define('post', attributes, { defaultScope: { where: { active: true } }, scopes: { deleted: { where: { deleted: true } } } }); User.hasMany(Post); // 常規 getPosts 關聯 User.hasMany(Post.scope('deleted'), { as: 'deletedPosts' });
User.getPosts(); // WHERE active = true User.getDeletedPosts(); // WHERE deleted = true
若是這篇文章對您有幫助, 感謝 下方點贊 或 Star GitHub: sequelize-docs-Zh-CN 支持, 謝謝.