- vừa được xem lúc

Định nghĩa model quan hệ trong go-pg

0 0 8

Người đăng: Nguyen Tran Nhat Duc

Theo Viblo Asia

Xem source code tại đây

Trong phần trước mình đã đưa ra ví dụ giúp hiểu được một cách bao quát những lệnh truy vấn căn bản, định nghĩa model go-pg. Trước khi đi vào bổ sung, cải tiến ví dụ đó, trong bài này mình sẽ nói rõ về định nghĩa model và quan hệ giữa các model để giúp bạn hiểu bản chất.

1. Giới thiệu

Go-pg sử dụng công nghệ ORM (tức Object-relation mapping) giúp ánh xạ bảng cơ sở dữ liệu vào trong struct

Điều đấy có nghĩa là với mỗi struct trong golang có thể dùng làm đại diện để truy vấn đến bảng trong postgresql và trả ra đối tượng struct với giá trị tương ứng.

2. Cách định nghĩa model, tên struct, tên cột hợp lý

Go-pg có thể tự động nhận biết tên trường, tên struct, kiểu biến để khởi tạo bảng trong postgresql. Ví dụ:

  • nếu tên struct là Genre sẽ mặc định có tên bảng là genres
  • tên trường là FullName sẽ có tên cột là full_name
  • Kiểu string sẽ tương ứng với kiểu text trong database, int thành bigint,...
  • Trường có tên là Id tự động được thêm vào primary key.

Nếu không muốn để mặc định thì có thể ghi đè bằng những tags như: pg:"type:kiểu", pg:"tên cột",... hay thêm các ràng buộc cho cột như pg:,unique

Có thể tham khảo thêm tại đây

Ví dụ về định nghĩa model:

type User struct{ tableName struct{} `pg:"auth.users"` //Tên schema auth, bảng users Id int `pg:"type:serial,pk"` //Cột id đặt là primary key, với kiểu là serial FirstName string //String sẽ tương ứng với kiểu text trong database, tên cột là first_name LastName string //tên cột là last_name Email string `pg:",unique"` //Email điều kiện là không được trùng lặp Password string
}
  • Trường Id trong model User trên thay vì để kiểu mặc định là bigint, ta thay bằng serial. Và đuôi ,pk không thực sự cần thiết vì id sẽ mặc định là primary key
  • Nếu bỏ dòng tableName thì tên table sẽ mặc định là users. Nếu muốn ghi đè tên mặc định hoặc tạo bảng trong một schema thì đây là điều bắt buộc

3. Định nghĩa model quan hệ 1 - 1

Giả sử ta có 2 bảng User với Profile, với mỗi User chỉ có một Profile và ngược lại. Đây là quan hệ một một. Ta có thể định nghĩa model như sau

type User struct{ tableName struct{} `pg:"auth.users"` Id int `pg:"serial"` Name string Profile *Profile `pg:"rel:belongs-to"` //Profile thuộc về User
}
type Profile struct{ tableName struct{} `pg:"auth.profile"` Id int `pg:"type:serial"` Avatar string UserId int `pg:",unique"` //Id của User mà Profile thuộc về, đây là trường cần thiết để go-pg hiểu được quan hệ
}

Lưu ý: - Việc đặt unique ở UserId trong Profile không bắt buộc, chỉ nhằm để không có UserId nào giống nhau, như vậy sẽ đảm bảo quan hệ thực sự là 1 - 1 hơn. Nếu không có unique ta có thể có 2 Profile với cùng một UserId, như vậy sẽ mất đi bản chất quan hệ 1 - 1.

4. Định nghĩa model quan hệ 1 - nhiều

Một user có thể có nhiều bài post. Ta có thể định nghĩa model thể hiện quan hệ này như sau:

type User struct{ tableName struct{} `pg:"auth.users"` Name string //Với mỗi user có thể lấy ra nhiều bài post của chính user đó Posts []Post `pg:"rel:has-many,join_fk:user_id"`
}

Lưu ý: chỉ nên dùng join_fk khi ta muốn sử dụng foreign key với tên khác mặc định. Trong ví dụ trên không thực sự cần thiết

type Post struct{ tableName struct{} `pg:"blog.post"` Id int `pg:"type:serial" ` Content string `pg:",notnull"` Title string `pg:",notnull"` //Đây là trường cần thiết để go-pg hiểu được quan hệ, nếu thay đổi cần thay đổi giá trị join_fk ở User trên UserId int `pg:"type:integer"` User *User `pg:"rel:has-one"` //Mỗi post có thể lấy 1 user
}

5. Định nghĩa model quan hệ nhiều - nhiều

Một User có nhiều Role (như admin, teacher,...) và ngược lại một Role cũng có thể có nhiều User. Đây là quan hệ nhiều - nhiều. Trong quan hệ nhiều - nhiều, cách thường thấy là tạo bảng thứ 3 chứa hai id của 2 bảng còn lại. Ta có thể định nghĩa model thể hiện quan hệ này như sau:

type User struct{ tableName struct{} `pg:"auth.users"` Id int `pg:"type:serial"` Name string //Quan hệ nhiều nhiều tham chiếu đến bảng auth.user_role để lấy giá trị Roles []Role `pg:"many2many:auth.user_role"`
}
type Role struct{ tableName struct{} `pg:"auth.role"` Id int `pg:"type:serial"` Name string
}
//Bảng thứ 3 tên auth.user_role thể hiện quan hệ giữa 2 bảng trên
type UserRole struct{ tableName struct{} `pg:"auth.user_role"` UserId int // Id của User RoleId int // Id của Role
}

Để ORM hiểu được bảng user_role là bảng thể hiện quan hệ nhiều - nhiều của 2 bảng user và role. Ta cần dùng hàm RegisterTable như sau:

 orm.RegisterTable((*UserRole)(nil)) 

Lưu ý: ta cần chạy hàm này trước khi các model User và Role được sử dụng đến, cách tốt nhất là chạy ngay từ đầu khi mới bắt đầu kết nối database.

Kết

Việc định nghĩa struct model golang cũng chính là đang tạo bảng trong postgresql. Đây là bước cần thiết để ta có thể thao tác với cơ sở dữ liệu sau này. Trong phần sau mình sẽ đi vào ví dụ thực tế, chi tiết hơn cùng với các lệnh truy vấn JOIN bảng.

Bình luận

Bài viết tương tự

- vừa được xem lúc

gRPC - Nó là gì và có nên sử dụng hay không?

Nhân một ngày rảnh rỗi, mình ngồi đọc lại RPC cũng như gRPC viết lại để nhớ lâu hơn. Vấn đề là gì và tại sao cần nó .

0 0 131

- vừa được xem lúc

Embedded Template in Go

Getting Start. Part of developing a web application usually revolves around working with HTML as user interface.

0 0 56

- vừa được xem lúc

Tạo Resful API đơn giản với Echo framework và MySQL

1. Giới thiệu.

0 0 60

- vừa được xem lúc

Sử dụng goquery trong golang để crawler thông tin các website Việt Nam bị deface trên mirror-h.org

. Trong bài viết này, mình sẽ cùng mọi người khám phá một package thu thập dữ liệu có tên là goquery của golang. Mục tiêu chính của chương trình crawler này sẽ là lấy thông tin các website Việt Nam bị deface (là tấn công, phá hoại website, làm thay đổi giao diện hiển thị của một trang web, khi người

0 0 237

- vừa được xem lúc

Tạo ứng dụng craw dữ liệu bing với Golang, Mysql driver

Chào mọi người . Lâu lâu ta lại gặp nhau 1 lần, để tiếp tục series chia sẻ kiến thức về tech, hôm nay mình sẽ tìm hiểu và chia sẻ về 1 ngôn ngữ đang khá hot trong cộng đồng IT đó là Golang.

0 0 75

- vừa được xem lúc

Golang: Rest api and routing using MUX

Routing with MUX. Let's create a simple CRUD api for a blog site. # All . GET articles/ .

0 0 54