Use the Association API to find, append, replace, delete, clear, and count associated records on a loaded model.
Association mode provides a set of helper methods for working with relationships on an already-loaded model instance. Access it by calling db.Model(&record).Association("FieldName").
// Association struct (from association.go)// type Association struct {// DB *DB// Relationship *schema.Relationship// Unscope bool// Error error// }association := db.Model(&user).Association("Languages")if association.Error != nil { // handle error}
You must have a loaded model value (with a valid primary key) before calling Association. GORM uses the model’s primary key to scope all queries.
// Replace all languages with a new listdb.Model(&user).Association("Languages").Replace( []Language{{Name: "English"}, {Name: "Chinese"}},)// For has_one / belongs_to — replace the single associated recorddb.Model(&user).Association("CreditCard").Replace(&CreditCard{Number: "4111-1111-1111-1111"})
For has one and has many, the old associated records have their foreign keys set to NULL. For many to many, the old join table rows are deleted.
// Remove a single recorddb.Model(&user).Association("Languages").Delete(&language)// Remove multiple recordsdb.Model(&user).Association("CreditCards").Delete( &CreditCard{ID: 1}, &CreditCard{ID: 2},)// Remove using a slicedb.Model(&user).Association("CreditCards").Delete(&[]CreditCard{{ID: 3}, {ID: 4}})
Delete only removes the association link:
For has one / has many: sets the foreign key to NULL.
For many to many: deletes the join table row.
For belongs to: sets the foreign key on the owner to NULL.
The associated records themselves are not deleted from their table unless you use Unscoped.
db.Model(&user).Association("Languages").Clear()// Removes all rows from user_languages for this userdb.Model(&user).Association("CreditCards").Clear()// Sets user_id = NULL on all credit cards belonging to this user
Clear is equivalent to calling Replace with no arguments.
By default, Delete and Clear only unlink associations (set foreign keys to NULL or delete join rows). Use Unscoped() to permanently delete the associated records themselves:
// Permanently delete the associated credit card recorddb.Model(&user).Association("CreditCard").Unscoped().Delete(&creditCard)// Permanently delete all associated recordsdb.Model(&user).Association("CreditCards").Unscoped().Clear()
Unscoped().Clear() permanently deletes the associated records from the database, not just the link. Use with caution.
When using soft-delete models, Unscoped also makes Find return soft-deleted records:
var languages []Languagedb.Model(&user).Association("Languages").Unscoped().Find(&languages)// Includes soft-deleted languages
All Association methods support batch operations when the model is a slice. Each element in the model slice maps positionally to the corresponding element in the values slice:
var users []Userdb.Find(&users)// Append one language per user (positional mapping)db.Model(&users).Association("Languages").Append( []Language{{Name: "English"}, {Name: "French"}, {Name: "Spanish"}},)// users[0] gets English, users[1] gets French, users[2] gets Spanish// Clear all language associations for every user in the slicedb.Model(&users).Association("Languages").Clear()
When using Append or Replace with a slice model, the values slice length must match the model slice length. A mismatch returns ErrInvalidValueOfLength.