You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

5.5 KiB

Preloading (Eager Loading) Preload GORM allows eager loading relations in other SQL with Preload, for example:

type User struct { gorm.Model Username string Orders []Order }

type Order struct { gorm.Model UserID uint Price float64 }

// Preload Orders when find users db.Preload("Orders").Find(&users) // SELECT _ FROM users; // SELECT _ FROM orders WHERE user_id IN (1,2,3,4);

db.Preload("Orders").Preload("Profile").Preload("Role").Find(&users) // SELECT _ FROM users; // SELECT _ FROM orders WHERE user_id IN (1,2,3,4); // has many // SELECT _ FROM profiles WHERE user_id IN (1,2,3,4); // has one // SELECT _ FROM roles WHERE id IN (4,5,6); // belongs to Joins Preloading Preload loads the association data in a separate query, Join Preload will loads association data using left join, for example:

db.Joins("Company").Joins("Manager").Joins("Account").First(&user, 1) db.Joins("Company").Joins("Manager").Joins("Account").First(&user, "users.name = ?", "jinzhu") db.Joins("Company").Joins("Manager").Joins("Account").Find(&users, "users.id IN ?", []int{1,2,3,4,5}) Join with conditions

db.Joins("Company", DB.Where(&Company{Alive: true})).Find(&users) // SELECT users.id,users.name,users.age,Company.id AS Company__id,Company.name AS Company__name FROM users LEFT JOIN companies AS Company ON users.company_id = Company.id AND Company.alive = true; Join nested model

db.Joins("Manager").Joins("Manager.Company").Find(&users) // SELECT "users"."id","users"."created_at","users"."updated_at","users"."deleted_at","users"."name","users"."age","users"."birthday","users"."company_id","users"."manager_id","users"."active","Manager"."id" AS "Managerid","Manager"."created_at" AS "Managercreated_at","Manager"."updated_at" AS "Managerupdated_at","Manager"."deleted_at" AS "Managerdeleted_at","Manager"."name" AS "Managername","Manager"."age" AS "Managerage","Manager"."birthday" AS "Managerbirthday","Manager"."company_id" AS "Managercompany_id","Manager"."manager_id" AS "Managermanager_id","Manager"."active" AS "Manageractive","ManagerCompany"."id" AS "ManagerCompanyid","ManagerCompany"."name" AS "ManagerCompanyname" FROM "users" LEFT JOIN "users" "Manager" ON "users"."manager_id" = "Manager"."id" AND "Manager"."deleted_at" IS NULL LEFT JOIN "companies" "ManagerCompany" ON "Manager"."company_id" = "ManagerCompany"."id" WHERE "users"."deleted_at" IS NULL NOTE Join Preload works with one-to-one relation, e.g: has one, belongs to

Preload All clause.Associations can work with Preload similar like Select when creating/updating, you can use it to Preload all associations, for example:

type User struct { gorm.Model Name string CompanyID uint Company Company Role Role Orders []Order }

db.Preload(clause.Associations).Find(&users) clause.Associations won’t preload nested associations, but you can use it with Nested Preloading together, e.g:

db.Preload("Orders.OrderItems.Product").Preload(clause.Associations).Find(&users) Preload with conditions GORM allows Preload associations with conditions, it works similar to Inline Conditions

// Preload Orders with conditions db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users) // SELECT _ FROM users; // SELECT _ FROM orders WHERE user_id IN (1,2,3,4) AND state NOT IN ('cancelled');

db.Where("state = ?", "active").Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users) // SELECT _ FROM users WHERE state = 'active'; // SELECT _ FROM orders WHERE user_id IN (1,2) AND state NOT IN ('cancelled'); Custom Preloading SQL You are able to custom preloading SQL by passing in func(db *gorm.DB) *gorm.DB, for example:

db.Preload("Orders", func(db *gorm.DB) *gorm.DB { return db.Order("orders.amount DESC") }).Find(&users) // SELECT _ FROM users; // SELECT _ FROM orders WHERE user_id IN (1,2,3,4) order by orders.amount DESC; Nested Preloading GORM supports nested preloading, for example:

db.Preload("Orders.OrderItems.Product").Preload("CreditCard").Find(&users)

// Customize Preload conditions for Orders // And GORM won't preload unmatched order's OrderItems then db.Preload("Orders", "state = ?", "paid").Preload("Orders.OrderItems").Find(&users) Embedded Preloading Embedded Preloading is used for Embedded Struct, especially the same struct. The syntax for Embedded Preloading is similar to Nested Preloading, they are divided by dot.

For example:

type Address struct { CountryID int Country Country }

type Org struct { PostalAddress Address gorm:"embedded;embeddedPrefix:postal_address_" VisitingAddress Address gorm:"embedded;embeddedPrefix:visiting_address_" Address struct { ID int Address } }

// Only preload Org.Address and Org.Address.Country db.Preload("Address.Country") // "Address" is has_one, "Country" is belongs_to (nested association)

// Only preload Org.VisitingAddress db.Preload("PostalAddress.Country") // "PostalAddress.Country" is belongs_to (embedded association)

// Only preload Org.NestedAddress db.Preload("NestedAddress.Address.Country") // "NestedAddress.Address.Country" is belongs_to (embedded association)

// All preloaded include "Address" but exclude "Address.Country", because it won't preload nested associations. db.Preload(clause.Associations) We can omit embedded part when there is no ambiguity.

type Address struct { CountryID int Country Country }

type Org struct { Address Address gorm:"embedded" }

db.Preload("Address.Country") db.Preload("Country") // omit "Address" because there is no ambiguity NOTE Embedded Preload only works with belongs to relation. Values of other relations are the same in database, we can’t distinguish them.