The link http://gorm.io/docs/preload.html talks about preloading in GORM, but I am unable to understand what this function does.
type User struct {
gorm.Model
Username string
Orders Order
}
type Order struct {
gorm.Model
UserID uint
Price float64
}
db.Preload("Username")
db.Preload("Orders").Find(&users)
Can someone explain what will these 2 statements do? What will be the output ?
Is it that preload
is used to cache the results?
Preload. GORM allows eager loading relations in other SQL with Preload , for example: type User struct { gorm.Model. Username string.
preload initiates two queries, the first to fetch the primary model and the second to fetch associated models whereas eager_load does a left join which initiates one query to fetch both primary and associated models. preload is much better than eager_load in terms of memory usage.
GORM provides CRUD operations and can also be used for the initial migration and creation of the database schema. A few more things that GORM does well includes it's extendability with native plugin support, it's reliance on testing, and one-to-one and one-to-many group of associations.
The link you provided shows what it does. You just have to actually read the information on the page.
First of all, this doesn't really do anything:
db.Preload("Username")
On the other hand, the following:
db.Preload("Orders").Find(&users)
Does do something. First it populates users
and then it populates []user.Orders
. On the comments on the page you linked you will find this, which shows what it does by query:
db.Preload("Orders").Find(&users)
//// SELECT * FROM users;
//// SELECT * FROM orders WHERE user_id IN (1,2,3,4);
So what does this really do? I can give you the technical answer, which you can easily find out by googling eager loading or I can give you an answer by example which I feel is simpler.
So let me explain this by example.
Say you have users, where each user can have multiple orders. This is a one to many relationship which can be defined like:
type User struct {
gorm.Model
Username string
Orders []Order
}
When you populate your users
slice like:
db.Find(&users)
//// SELECT * FROM users;
If you need to get all the orders for each user you can easily access user.Orders
but this would be empty anyway because it didn't get populated.
If we populate users
slice like:
db.Preload("Orders").Find(&users)
The user.Orders
will be populated by the orders of that user. This is an abstraction that makes dealing with relationships easier.
The ugly alternative would be:
db.Find(&users)
for user := range users {
db.Where("user_id", user.id).Find(&user.Orders)
}
It will also make more request to the database than necessary. (which is not good)
If your users has Posts and Comments and Orders then you can define and query it like this:
type User struct {
gorm.Model
Username string
Orders []Order
Comments []Comment
Posts []Post
}
db.Preload("Orders").Preload("Comments").Preload("Posts").Find(&users)
With just the code above you can now have access to the users data in different tables in the database.
I hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With