此係列文章的應用示例已發佈於 GitHub: sequelize-docs-Zh-CN. 能夠 Fork 幫助改進或 Star 關注更新. 歡迎 Star.html
本部分描述 sequelize 中的各類關聯類型。 當調用 User.hasOne(Project)
這樣的方法時,咱們說 User
模型(該函數被調用的模型)是 source 而 Project
模型(模型被傳遞爲參數)是 target 。github
一對一關聯是經過單個外鍵鏈接的兩個模型之間的關聯。sql
BelongsTo 關聯是在 source model 上存在一對一關係的外鍵的關聯。數據庫
一個簡單的例子是 Player 經過 player 的外鍵做爲 Team 的一部分。segmentfault
const Player = this.sequelize.define('player', {/* attributes */}); const Team = this.sequelize.define('team', {/* attributes */}); Player.belongsTo(Team); // 將向 Team 添加一個 teamId 屬性以保存 Team 的主鍵值
默認狀況下,將從目標模型名稱和目標主鍵名稱生成 belongsTo 關係的外鍵。數組
默認的樣式是 camelCase
,可是若是源模型配置爲 underscored: true
,那麼 foreignKey 將是snake_case
。安全
const User = this.sequelize.define('user', {/* attributes */}) const Company = this.sequelize.define('company', {/* attributes */}); User.belongsTo(Company); // 將 companyId 添加到 user const User = this.sequelize.define('user', {/* attributes */}, {underscored: true}) const Company = this.sequelize.define('company', { uuid: { type: Sequelize.UUID, primaryKey: true } }); User.belongsTo(Company); // 將 company_uuid 添加到 user
在已定義 as
的狀況下,將使用它代替目標模型名稱。ide
const User = this.sequelize.define('user', {/* attributes */}) const UserRole = this.sequelize.define('userRole', {/* attributes */}); User.belongsTo(UserRole, {as: 'role'}); // 將 role 添加到 user 而不是 userRole
在全部狀況下,默認外鍵能夠用 foreignKey
選項覆蓋。
當使用外鍵選項時,Sequelize 將按原樣使用:函數
const User = this.sequelize.define('user', {/* attributes */}) const Company = this.sequelize.define('company', {/* attributes */}); User.belongsTo(Company, {foreignKey: 'fk_company'}); // 將 fk_company 添加到 User
目標鍵是源模型上的外鍵列指向的目標模型上的列。 默認狀況下,belongsTo 關係的目標鍵將是目標模型的主鍵。 要定義自定義列,請使用 targetKey
選項。
const User = this.sequelize.define('user', {/* attributes */}) const Company = this.sequelize.define('company', {/* attributes */}); User.belongsTo(Company, {foreignKey: 'fk_companyname', targetKey: 'name'}); // 添加 fk_companyname 到 User
HasOne 關聯是在 target model 上存在一對一關係的外鍵的關聯。
const User = sequelize.define('user', {/* ... */}) const Project = sequelize.define('project', {/* ... */}) // 單向關聯 Project.hasOne(User) /* 在此示例中,hasOne 將向 User 模型添加一個 projectId 屬性 ! 此外,Project.prototype 將根據傳遞給定義的第一個參數獲取 getUser 和 setUser 的方法。 若是啓用了 underscore 樣式,則添加的屬性將是 project_id 而不是 projectId。 外鍵將放在 users 表上。 你也能夠定義外鍵,例如 若是您已經有一個現有的數據庫而且想要處理它: */ Project.hasOne(User, { foreignKey: 'initiator_id' }) /* 由於Sequelize將使用模型的名稱(define的第一個參數)做爲訪問器方法, 還能夠將特殊選項傳遞給hasOne: */ Project.hasOne(User, { as: 'Initiator' }) // 如今你能夠得到 Project#getInitiator 和 Project#setInitiator // 或者讓咱們來定義一些本身的參考 const Person = sequelize.define('person', { /* ... */}) Person.hasOne(Person, {as: 'Father'}) // 這會將屬性 FatherId 添加到 Person // also possible: Person.hasOne(Person, {as: 'Father', foreignKey: 'DadId'}) // 這將把屬性 DadId 添加到 Person // 在這兩種狀況下,你均可以: Person#setFather Person#getFather // 若是你須要聯結表兩次,你能夠聯結同一張表 Team.hasOne(Game, {as: 'HomeTeam', foreignKey : 'homeTeamId'}); Team.hasOne(Game, {as: 'AwayTeam', foreignKey : 'awayTeamId'}); Game.belongsTo(Team);
即便它被稱爲 HasOne 關聯,對於大多數1:1關係,您一般須要BelongsTo關聯,由於 BelongsTo 將會在 hasOne 將添加到目標的源上添加 foreignKey。
在Sequelize 1:1關係中可使用HasOne和BelongsTo進行設置。 它們適用於不一樣的場景。 讓咱們用一個例子來研究這個差別。
假設咱們有兩個表能夠連接 Player 和 Team 。 讓咱們定義他們的模型。
const Player = this.sequelize.define('player', {/* attributes */}) const Team = this.sequelize.define('team', {/* attributes */});
當咱們鏈接 Sequelize 中的兩個模型時,咱們能夠將它們稱爲一對 source 和 target 模型。像這樣
將 Player 做爲 source 而 Team 做爲 target
Player.belongsTo(Team); //或 Player.hasOne(Team);
將 Team 做爲 source 而 Player 做爲 target
Team.belongsTo(Player); //Or Team.hasOne(Player);
HasOne 和 BelongsTo 將關聯鍵插入到不一樣的模型中。 HasOne 在 target 模型中插入關聯鍵,而 BelongsTo 將關聯鍵插入到 source 模型中。
下是一個示例,說明了 BelongsTo 和 HasOne 的用法。
const Player = this.sequelize.define('player', {/* attributes */}) const Coach = this.sequelize.define('coach', {/* attributes */}) const Team = this.sequelize.define('team', {/* attributes */});
假設咱們的 Player
模型有關於其團隊的信息爲 teamId
列。 關於每一個團隊的 Coach
的信息做爲 coachId
列存儲在 Team
模型中。 這兩種狀況都須要不一樣種類的1:1關係,由於外鍵關係每次出如今不一樣的模型上。
當關於關聯的信息存在於 source 模型中時,咱們可使用 belongsTo
。 在這種狀況下,Player
適用於 belongsTo
,由於它具備 teamId
列。
Player.belongsTo(Team) // `teamId` 將被添加到 Player / Source 模型中
當關於關聯的信息存在於 target 模型中時,咱們可使用 hasOne
。 在這種狀況下, Coach
適用於 hasOne
,由於 Team
模型將其 Coach
的信息存儲爲 coachId
字段。
Coach.hasOne(Team) // `coachId` 將被添加到 Team / Target 模型中
一對多關聯將一個來源與多個目標鏈接起來。 而多個目標接到同一個特定的源。
const User = sequelize.define('user', {/* ... */}) const Project = sequelize.define('project', {/* ... */}) // 好。 如今,事情變得更加複雜(對用戶來講並不真實可見)。 // 首先咱們來定義一個 hasMany 關聯 Project.hasMany(User, {as: 'Workers'})
這將添加屬性 projectId
或 project_id
到 User。 Project 的實例將得到訪問器 getWorkers
和 setWorkers
。 咱們讓它保持原樣,讓它成爲單向關聯。
可是咱們想要更多! 讓咱們在下一節中以其餘方式定義並建立一個多對多的關聯:
有時您可能須要在不一樣的列上關聯記錄,您可使用 sourceKey
選項:
const City = sequelize.define('city', { countryCode: Sequelize.STRING }); const Country = sequelize.define('country', { isoCode: Sequelize.STRING }); // 在這裏,咱們能夠根據國家代碼鏈接國家和城市 Country.hasMany(City, {foreignKey: 'countryCode', sourceKey: 'isoCode'}); City.belongsTo(Country, {foreignKey: 'countryCode', targetKey: 'isoCode'});
多對多關聯用於將源與多個目標相鏈接。 此外,目標也能夠鏈接到多個源。
Project.belongsToMany(User, {through: 'UserProject'}); User.belongsToMany(Project, {through: 'UserProject'});
這將建立一個名爲 UserProject 的新模型,具備等效的外鍵projectId
和userId
。 屬性是否爲camelcase
取決於由表(在這種狀況下爲User
和Project
)鏈接的兩個模型。
定義 through
爲 required。 Sequelize 之前會嘗試自動生成名稱,但並不老是致使最合乎邏輯的設置。
這將添加方法 getUsers
, setUsers
, addUser
,addUsers
到 Project
, 還有 getProjects
, setProjects
, addProject
, 和 addProjects
到 User
.
有時,您可能須要在關聯中使用它們時重命名模型。 讓咱們經過使用別名(as
)選項將 users 定義爲 workers 而 projects 定義爲t asks。 咱們還將手動定義要使用的外鍵:
User.belongsToMany(Project, { as: 'Tasks', through: 'worker_tasks', foreignKey: 'userId' }) Project.belongsToMany(User, { as: 'Workers', through: 'worker_tasks', foreignKey: 'projectId' })
foreignKey
將容許你在 through 關係中設置 source model 鍵。
otherKey
將容許你在 through 關係中設置 target model 鍵。
User.belongsToMany(Project, { as: 'Tasks', through: 'worker_tasks', foreignKey: 'userId', otherKey: 'projectId'})
固然你也可使用 belongsToMany 定義自我引用:
Person.belongsToMany(Person, { as: 'Children', through: 'PersonChildren' }) // 這將建立存儲對象的 ID 的表 PersonChildren。
若是您想要鏈接表中的其餘屬性,則能夠在定義關聯以前爲鏈接表定義一個模型,而後再說明它應該使用該模型進行鏈接,而不是建立一個新的關聯:
const User = sequelize.define('user', {}) const Project = sequelize.define('project', {}) const UserProjects = sequelize.define('userProjects', { status: DataTypes.STRING }) User.belongsToMany(Project, { through: UserProjects }) Project.belongsToMany(User, { through: UserProjects })
要向 user 添加一個新 project 並設置其狀態,您能夠將額外的 options.through
傳遞給 setter,其中包含鏈接表的屬性
user.addProject(project, { through: { status: 'started' }})
默認狀況下,上面的代碼會將 projectId 和 userId 添加到 UserProjects 表中, 刪除任何先前定義的主鍵屬性 - 表將由兩個表的鍵的組合惟一標識,而且沒有其餘主鍵列。 要在 UserProjects
模型上強添加一個主鍵,您能夠手動添加它。
const UserProjects = sequelize.define('userProjects', { id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true }, status: DataTypes.STRING })
使用多對多你能夠基於 through 關係查詢並選擇特定屬性。 例如經過 through 使用findAll
User.findAll({ include: [{ model: Project, through: { attributes: ['createdAt', 'startedAt', 'finishedAt'], where: {completed: true} } }] });
本節涉及關聯做用域。 有關關聯做用域與相關模型上的做用域的定義,請參閱 做用域。
關聯做用域容許您在關聯上放置一個做用域(一套 get
和 create
的默認屬性)。做用域能夠放在相關聯的模型(關聯的target)上,也能夠經過表上的 n:m 關係。
假設咱們有表評論,帖子和圖像。 一個評論能夠經過 commentable_id
和 commentable
關聯到一個圖像或一個帖子 - 咱們說 Post 和 Image 是 Commentable
const Comment = this.sequelize.define('comment', { title: Sequelize.STRING, commentable: Sequelize.STRING, commentable_id: Sequelize.INTEGER }); Comment.prototype.getItem = function(options) { return this['get' + this.get('commentable').substr(0, 1).toUpperCase() + this.get('commentable').substr(1)](options); }; Post.hasMany(this.Comment, { foreignKey: 'commentable_id', constraints: false, scope: { commentable: 'post' } }); Comment.belongsTo(this.Post, { foreignKey: 'commentable_id', constraints: false, as: 'post' }); Image.hasMany(this.Comment, { foreignKey: 'commentable_id', constraints: false, scope: { commentable: 'image' } }); Comment.belongsTo(this.Image, { foreignKey: 'commentable_id', constraints: false, as: 'image' });
constraints: false,
禁用引用約束 - 因爲 commentable_id
列引用了幾個表,咱們不能添加一個 REFERENCES
約束。 請注意,Image - > Comment 和 Post - > Comment 關係分別定義了一個做用域:commentable: 'image'
和 commentable: 'post'
。 使用關聯功能時自動應用此做用域:
image.getComments() SELECT * FROM comments WHERE commentable_id = 42 AND commentable = 'image'; image.createComment({ title: 'Awesome!' }) INSERT INTO comments (title, commentable_id, commentable) VALUES ('Awesome!', 42, 'image'); image.addComment(comment); UPDATE comments SET commentable_id = 42, commentable = 'image'
Comment
上的 getItem
做用函數完成了圖片 - 它只是將commentable
字符串轉換爲getImage
或getPost
的一個調用,提供一個註釋是屬於一個帖子仍是一個圖像的抽象概念。您能夠將普通選項對象做爲參數傳遞給 getItem(options)
,以指定任何條件或包含的位置。
繼續多態模型的思路,考慮一個 tag 表 - 一個 item 能夠有多個 tag,一個 tag 能夠與多個 item 相關。
爲了簡潔起見,該示例僅顯示了 Post 模型,但實際上 Tag 與其餘幾個模型相關。
const ItemTag = sequelize.define('item_tag', { id : { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, tag_id: { type: DataTypes.INTEGER, unique: 'item_tag_taggable' }, taggable: { type: DataTypes.STRING, unique: 'item_tag_taggable' }, taggable_id: { type: DataTypes.INTEGER, unique: 'item_tag_taggable', references: null } }); const Tag = sequelize.define('tag', { name: DataTypes.STRING }); Post.belongsToMany(Tag, { through: { model: ItemTag, unique: false, scope: { taggable: 'post' } }, foreignKey: 'taggable_id', constraints: false }); Tag.belongsToMany(Post, { through: { model: ItemTag, unique: false }, foreignKey: 'tag_id', constraints: false });
請注意,做用域列(taggable
)如今在 through 模型(ItemTag
)上。
咱們還能夠定義一個更具限制性的關聯,例如,經過應用through 模型(ItemTag
)和目標模型(Tag
)的做用域來獲取全部掛起的 tag。
Post.hasMany(Tag, { through: { model: ItemTag, unique: false, scope: { taggable: 'post' } }, scope: { status: 'pending' }, as: 'pendingTags', foreignKey: 'taggable_id', constraints: false }); Post.getPendingTags();
SELECT `tag`.* INNER JOIN `item_tags` AS `item_tag` ON `tag`.`id` = `item_tag`.`tagId` AND `item_tag`.`taggable_id` = 42 AND `item_tag`.`taggable` = 'post' WHERE (`tag`.`status` = 'pending');
constraints: false
禁用 taggable_id
列上的引用約束。 由於列是多態的,咱們不能說它是 REFERENCES
一個特定的表。
默認狀況下,Sequelize將使用模型名稱(傳遞給sequelize.define
的名稱),以便在關聯時使用模型名稱。 例如,一個名爲user
的模型會將關聯模型的實例中的get / set / add User
函數和加入一個名爲.user
的屬性,而一個名爲User
的模型會添加相同的功能,和一個名爲.User
的屬性(注意大寫U)。
正如咱們已經看到的,你可使用as
來關聯模型。 在單個關聯(has one 和 belongs to),別名應該是單數,而對於許多關聯(has many)它應該是複數。 Sequelize而後使用[inflection] [0]庫將別名轉換爲其單數形式。 可是,這可能並不老是適用於不規則或非英語單詞。 在這種狀況下,您能夠提供複數和單數形式的別名:
User.belongsToMany(Project, { as: { singular: 'task', plural: 'tasks' }}) // Notice that inflection has no problem singularizing tasks, this is just for illustrative purposes.
若是你知道模型將始終在關聯中使用相同的別名,則能夠在建立模型時提供它
const Project = sequelize.define('project', attributes, { name: { singular: 'task', plural: 'tasks', } }) User.belongsToMany(Project);
這將爲用戶實例添加 add/set/get Tasks
方法。
記住,使用as
來更改關聯的名稱也會改變外鍵的名稱。 當使用as
時,也能夠指定外鍵是最安全的。
Invoice.belongsTo(Subscription) Subscription.hasMany(Invoice)
不使用 as
,這會按預期添加 subscriptionId
。 可是,若是您要發送Invoice.belongsTo(Subscription, { as: 'TheSubscription' })
,那麼您將同時擁有 subscriptionId
和 theSubscriptionId
,由於 sequelize 不夠聰明,沒法肯定調用是相同關係的兩面。 foreignKey
修正了這個問題;
Invoice.belongsTo(Subscription, , { as: 'TheSubscription', foreignKey: 'subscription_id' }) Subscription.hasMany(Invoice, { foreignKey: 'subscription_id' )
由於 Sequelize 作了不少神奇的事,因此你必須在設置關聯後調用 Sequelize.sync
。 這樣作將容許您進行如下操做:
Project.belongsToMany(Task) Task.belongsToMany(Project) Project.create()... Task.create()... Task.create()... // 保存它們.. 而後: project.setTasks([task1, task2]).then(() => { // 已保存! }) // 好的,如今它們已經保存了...我怎麼才能獲得他們? project.getTasks().then(associatedTasks => { // associatedTasks 是一個 tasks 的數組 }) // 您還能夠將過濾器傳遞給getter方法。 // 它們與你能傳遞給常規查找器方法的選項相同。 project.getTasks({ where: 'id > 10' }).then(tasks => { // id大於10的任務 }) // 你也能夠僅檢索關聯對象的某些字段。 project.getTasks({attributes: ['title']}).then(tasks => { // 使用屬性「title」和「id」檢索任務 })
要刪除建立的關聯,您能夠調用set方法而不使用特定的ID:
// 刪除與 task1 的關聯 project.setTasks([task2]).then(associatedTasks => { // 你將只獲得 task2 }) // 刪除所有 project.setTasks([]).then(associatedTasks => { // 你將獲得空數組 }) // 或更直接地刪除 project.removeTask(task1).then(() => { // 什麼都沒有 }) // 而後再次添加它們 project.addTask(task1).then(function() { // 它們又回來了 })
反之亦然你固然也能夠這樣作:
// project與task1和task2相關聯 task2.setProject(null).then(function() { // 什麼都沒有 })
對於 hasOne/belongsTo 與其基本相同:
Task.hasOne(User, {as: "Author"}) Task#setAuthor(anAuthor)
能夠經過兩種方式添加與自定義鏈接表的關係的關聯(繼續前一章中定義的關聯):
// 在建立關聯以前,經過向對象添加具備鏈接表模型名稱的屬性 project.UserProjects = { status: 'active' } u.addProject(project) // 或者在添加關聯時提供第二個options.through參數,其中包含應該在鏈接表中的數據 u.addProject(project, { through: { status: 'active' }}) // 關聯多個對象時,能夠組合上述兩個選項。 在這種狀況下第二個參數 // 若是沒有提供使用的數據將被視爲默認對象 project1.UserProjects = { status: 'inactive' } u.setProjects([project1, project2], { through: { status: 'active' }}) // 上述代碼將對項目1記錄無效,而且在鏈接表中對項目2進行active
當獲取具備自定義鏈接表的關聯的數據時,鏈接表中的數據將做爲DAO實例返回:
u.getProjects().then(projects => { const project = projects[0] if (project.UserProjects.status === 'active') { // .. 作點什麼 // 因爲這是一個真正的DAO實例,您能夠在完成操做以後直接保存它 return project.UserProjects.save() } })
若是您僅須要鏈接表中的某些屬性,則能夠提供具備所需屬性的數組:
// 這將僅從 Projects 表中選擇 name,僅從 UserProjects 表中選擇status user.getProjects({ attributes: ['name'], joinTableAttributes: ['status']})
您還能夠檢查對象是否已經與另外一個對象相關聯(僅 n:m)。 這是你怎麼作的
// 檢查對象是不是關聯對象之一: Project.create({ /* */ }).then(project => { return User.create({ /* */ }).then(user => { return project.hasUser(user).then(result => { // 結果是 false return project.addUser(user).then(() => { return project.hasUser(user).then(result => { // 結果是 true }) }) }) }) }) // 檢查全部關聯的對象是否如預期的那樣: // 咱們假設咱們已經有一個項目和兩個用戶 project.setUsers([user1, user2]).then(() => { return project.hasUsers([user1]); }).then(result => { // 結果是 false return project.hasUsers([user1, user2]); }).then(result => { // 結果是 true })
當您在sequelize模型中建立關聯時,將自動建立具備約束的外鍵引用。 設置以下:
const Task = this.sequelize.define('task', { title: Sequelize.STRING }) const User = this.sequelize.define('user', { username: Sequelize.STRING }) User.hasMany(Task) Task.belongsTo(User)
將生成如下SQL:
CREATE TABLE IF NOT EXISTS `User` ( `id` INTEGER PRIMARY KEY, `username` VARCHAR(255) ); CREATE TABLE IF NOT EXISTS `Task` ( `id` INTEGER PRIMARY KEY, `title` VARCHAR(255), `user_id` INTEGER REFERENCES `User` (`id`) ON DELETE SET NULL ON UPDATE CASCADE );
在task和user的關係之 中在task上注入user_id
外鍵,並將其標記爲User
表的引用。默認狀況下,若是引用的用戶被刪除,user_id
將被設置爲NULL
,若是更新了用戶標識的id,則會被更新。經過將onUpdate
和onDelete
選項傳遞給關聯調用,能夠覆蓋這些選項。驗證選項爲RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL
。
對於1:1和1:m關聯,默認選項爲SET NULL
用於刪除, CASCADE
用於更新。對於n:m,二者的默認值爲CASCADE
。這意味着,若是從n:m關聯的一側刪除或更新行,引用該行的鏈接表中的全部行也將被刪除或更新。
在表之間添加約束意味着在使用sequelize.sync
時,必須以特定順序在數據庫中建立表。若是Task
引用了User
,則必須先建立User
表,而後才能建立Task
表。這有時可能致使循環引用,其中後遺症找不到要同步的順序。想象一下文件和版本的場景。一個文檔能夠有多個版本,爲方便起見,一個文檔能夠引用它的當前版本。
const Document = this.sequelize.define('document', { author: Sequelize.STRING }) const Version = this.sequelize.define('version', { timestamp: Sequelize.DATE }) Document.hasMany(Version) // 這將 document_id 添加到版本 Document.belongsTo(Version, { as: 'Current', foreignKey: 'current_version_id'}) // 這將current_version_id添加到文檔
可是,上面的代碼將致使如下錯誤: Cyclic dependency found. 'Document' is dependent of itself. Dependency Chain: Document -> Version => Document
.
爲了減輕這一點,咱們能夠將 constraints: false
傳遞給其中一個關聯:
Document.hasMany(Version) Document.belongsTo(Version, { as: 'Current', foreignKey: 'current_version_id', constraints: false})
這將容許咱們正確地同步表:
CREATE TABLE IF NOT EXISTS `Document` ( `id` INTEGER PRIMARY KEY, `author` VARCHAR(255), `current_version_id` INTEGER ); CREATE TABLE IF NOT EXISTS `Version` ( `id` INTEGER PRIMARY KEY, `timestamp` DATETIME, `document_id` INTEGER REFERENCES `Document` (`id`) ON DELETE SET NULL ON UPDATE CASCADE );
有時,您可能須要引用另外一個表,而不添加任何約束或關聯。 在這種狀況下,您能夠手動將引用屬性添加到模式定義,並標記它們之間的關係。
// 在咱們調用 Trainer.hasMany(series) 以後 Series 有一個 外參考鍵 trainer_id=Trainer.id const Series = sequelize.define('series', { title: DataTypes.STRING, sub_title: DataTypes.STRING, description: DataTypes.TEXT, // 用 `Trainer` 設置外鍵關係(hasMany) trainer_id: { type: DataTypes.INTEGER, references: { model: "trainers", key: "id" } } }) const Trainer = sequelize.define('trainer', { first_name: DataTypes.STRING, last_name: DataTypes.STRING }); // 在咱們調用 Series.hasOne(Video) 以後 Video 有一個 外參考鍵 series_id=Series.id const Video = sequelize.define('video', { title: DataTypes.STRING, sequence: DataTypes.INTEGER, description: DataTypes.TEXT, // 用 `Series` 設置關係(hasOne) series_id: { type: DataTypes.INTEGER, references: { model: Series, // 能夠是表示表名稱的字符串,也能夠是對模型的引用 key: "id" } } }); Series.hasOne(Video); Trainer.hasMany(Series);
若是全部元素都是新的,則能夠在一個步驟中建立具備嵌套關聯的實例。
考慮如下模型:
const Product = this.sequelize.define('product', { title: Sequelize.STRING }); const User = this.sequelize.define('user', { first_name: Sequelize.STRING, last_name: Sequelize.STRING }); const Address = this.sequelize.define('address', { type: Sequelize.STRING, line_1: Sequelize.STRING, line_2: Sequelize.STRING, city: Sequelize.STRING, state: Sequelize.STRING, zip: Sequelize.STRING, }); Product.User = Product.belongsTo(User); User.Addresses = User.hasMany(Address); // 也能用於 `hasOne`
能夠經過如下方式在一個步驟中建立一個新的Product
, User
和一個或多個Address
:
return Product.create({ title: 'Chair', user: { first_name: 'Mick', last_name: 'Broadstone', addresses: [{ type: 'home', line_1: '100 Main St.', city: 'Austin', state: 'TX', zip: '78704' }] } }, { include: [{ association: Product.User, include: [ User.Addresses ] }] });
這裏,咱們的用戶模型稱爲user
,帶小寫u - 這意味着對象中的屬性也應該是user
。 若是給sequelize.define
指定的名稱爲User
,對象中的鍵也應爲User
。 對於addresses
也是一樣的,除了它是一個 hasMany
關聯的複數。
能夠將前面的示例擴展爲支持關聯別名。
const Creator = Product.belongsTo(User, {as: 'creator'}); return Product.create({ title: 'Chair', creator: { first_name: 'Matt', last_name: 'Hansen' } }, { include: [ Creator ] });
咱們來介紹將產品與許多標籤相關聯的功能。 設置模型可能以下所示:
const Tag = this.sequelize.define('tag', { name: Sequelize.STRING }); Product.hasMany(Tag); // Also works for `belongsToMany`.
如今,咱們能夠經過如下方式建立具備多個標籤的產品:
Product.create({ id: 1, title: 'Chair', tags: [ { name: 'Alpha'}, { name: 'Beta'} ] }, { include: [ Tag ] })
而後,咱們能夠修改此示例以支持別名:
const Categories = Product.hasMany(Tag, {as: 'categories'}); Product.create({ id: 1, title: 'Chair', categories: [ {id: 1, name: 'Alpha'}, {id: 2, name: 'Beta'} ] }, { include: [{ model: Categories, as: 'categories' }] })
若是這篇文章對您有幫助, 感謝 下方點贊 或 Star GitHub: sequelize-docs-Zh-CN 支持, 謝謝.