Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does Preload function do in gorm?

Tags:

go

go-gorm

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?

like image 274
Harsh Agarwal Avatar asked Dec 24 '19 16:12

Harsh Agarwal


People also ask

What is preloading in Gorm?

Preload. GORM allows eager loading relations in other SQL with Preload , for example: type User struct { gorm.Model. Username string.

What is SQL preload?

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.

What is Gorm used for?

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.


1 Answers

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.

like image 98
majidarif Avatar answered Oct 18 '22 07:10

majidarif