go-pg là một thư viện ORM (Object-Relational Mapping) và trình điều khiển PostgreSQL cho ngôn ngữ lập trình Go. Nó cung cấp một cách tiện lợi để tương tác với cơ sở dữ liệu PostgreSQL bằng cách ánh xạ các cấu trúc (structs) trong Go thành các bảng trong cơ sở dữ liệu và ngược lại.

Ưu điểm của go-pg

  • Dễ sử dụng: Cung cấp API trực quan để thực hiện các thao tác CRUD (Create, Read, Update, Delete).
  • Hiệu suất cao: Được thiết kế để có hiệu suất tốt, tạo ra các truy vấn SQL hiệu quả.
  • Hỗ trợ đầy đủ tính năng của PostgreSQL: Tận dụng các tính năng riêng của PostgreSQL như Array, Hstore, JSONB, LISTEN/NOTIFY, COPY, v.v.
  • ORM và SQL thuần túy: Cho phép bạn làm việc với các model (structs) theo kiểu ORM hoặc viết các truy vấn SQL thuần túy khi cần kiểm soát chi tiết hơn.

Các tính năng chính của go-pg

Kết nối và Cấu hình:

  • Thiết lập kết nối với PostgreSQL bằng chuỗi kết nối hoặc các tùy chọn riêng biệt.
  • Hỗ trợ pool kết nối để quản lý hiệu quả các kết nối database.

Định nghĩa Model (Structs):

  • Ánh xạ các trường của struct Go với các cột trong bảng PostgreSQL bằng cách sử dụng struct tags.
  • Ví dụ: json:"id" để ánh xạ với JSON, pg:"column_name,notnull,unique" để cấu hình cột database.
  • Hỗ trợ các kiểu dữ liệu cơ bản của Go và PostgreSQL, bao gồm cả time.Time, net.IP, net.IPNet, sql.Null*.
  • Tự động chuyển đổi structs, maps, và slices thành JSON khi lưu trữ vào cột JSONB.

Truy vấn (Queries):

  • ORM-style queries:
    • db.Model(&user).Select(): Lấy dữ liệu.
    • db.Model(&user).Insert(): Chèn dữ liệu mới.
    • db.Model(&user).Where("id = ?", user.ID).Update(): Cập nhật dữ liệu.
    • db.Model(&user).Where("id = ?", user.ID).Delete(): Xóa dữ liệu.
    • Hỗ trợ các điều kiện Where, Limit, Offset, Order, Group, Having.
    • ColumnExpr: Cho phép bạn sử dụng các biểu thức SQL tùy chỉnh trong truy vấn.
  • Raw SQL queries:
    • db.Query(model, "SELECT * FROM users WHERE id = ?", id): Thực thi truy vấn SQL thuần túy và scan kết quả vào model hoặc biến.
    • db.Exec("UPDATE users SET name = ? WHERE id = ?", name, id): Thực thi các câu lệnh SQL không trả về hàng.

Quan hệ (Relations):

  • Hỗ trợ các loại quan hệ phổ biến:
    • Has One: Một-một.
    • Belongs To: Một-một (chiều ngược lại của Has One).
    • Has Many: Một-nhiều.
    • Many To Many: Nhiều-nhiều.
  • Sử dụng Relation để load các quan hệ trong truy vấn Select.

Giao dịch (Transactions):

  • Hỗ trợ các giao dịch cơ sở dữ liệu (BEGIN, COMMIT, ROLLBACK).
  • Có hàm tiện ích db.RunInTransaction để đơn giản hóa việc quản lý giao dịch (tự động rollback nếu có lỗi, commit nếu thành công).

Migrations (Di chuyển schema):

  • Cung cấp package github.com/go-pg/migrations để quản lý các thay đổi schema database theo thời gian.
  • Hỗ trợ cả migration bằng file SQL và migration bằng code Go.

Tính năng nâng cao:

  • Listeners và Notifiers: Tương tác với tính năng LISTENNOTIFY của PostgreSQL.
  • COPY: Chức năng COPY FROM/TO để nhập/xuất dữ liệu hàng loạt hiệu quả.
  • Hooks: Cho phép bạn thực thi code trước hoặc sau các thao tác database (ví dụ: BeforeInsert, AfterSelect).
  • Soft Deletes: Hỗ trợ xóa mềm (thay vì xóa hẳn record, chỉ đánh dấu nó là đã xóa).
  • Circuit Breaker và Retries: Hỗ trợ tự động thử lại truy vấn khi gặp lỗi mạng và circuit breaking để ngăn ngừa việc quá tải database.
  • Debugging: Có thể log các truy vấn SQL được tạo ra bởi go-pg để debug.

Ví dụ một số model quan hệ

Quan hệ One-to-One

type Profile struct {
  tableName struct{} `pg:"profiles"`

  ID int
  UserID int
  Bio string
}

type User struct {
  tableName struct{} `pg:"users"`

  ID int
  Name string
  Profile *Profile `pg:"rel:has-one"`
}
  • Một User có một Profile
  • Trường ProfileUserID làm khóa ngoại.

Quan hệ One-to-Many

type Post struct {
  tableName struct{} `pg:"posts"`

  ID int
  Title string
  UserID int
}

type User struct {
  tableName struct{} `pg:"users"`

  ID int
  Name string
  Posts []*Post `pg:"rel:has-many"`
}
  • Một User có nhiều Post
  • Trường UserID trong Post là khóa ngoại đến User

Quan hệ Many-to-Many (thông qua bảng trung gian)

type User struct {
  tableName struct{} `pg:"users"`

  ID int
  Name string
  Roles []Role `pg:"many2many:user_roles"`
}

type Role struct {
  tableName struct{} `pg:"roles"`

  ID int
  Name string
}

type UserRole struct {
  tableName struct{} `pg:"user_roles"`

  UserID int
  RoleID int
}
  • Một User có thể có nhiều Role
  • Một Role có thể gán cho nhiều User
  • Bảng user_roles là bảng trung gian

About the Author

Đức Phát

View all author's posts

Leave a Comment

Your email address will not be published. Required fields are marked *

Bài viết khác

Hệ quản trị CSDL PostgreSQL

SQL là gì? SQL (Structured Query Language) là viết tắt của Ngôn ngữ truy vấn có cấu trúc, là ngôn ngữ được tiêu chuẩn hóa để tương tác với các hệ thống quản lý cơ sở dữ liệu quan hệ (RDBMS). Cơ sở dữ liệu quan hệ là tập hợp dữ liệu được tổ chức thành các […]

PostgreSQL : subquery, CTE

What is subquery in PostgreSQL? In PostgreSQL, a subquery is a query that is nested inside another query. The subquery is executed first, and its results are used as input to the outer query. Subqueries can be used in various contexts, such as in the SELECT, WHERE, and HAVING clauses of a query. For example, […]

Optimize SQL : rule and todo list

Some rule and todo list to Optimize SQL REF https://www.pgmustard.com/blog/indexing-best-practices-postgresql

PostgreSQL Compound indexes

What is Compound indexes in PostgreSQL? A compound index (also known as a composite index or a multi-column index) refers to an index that is created on two or more columns of a table. It allows PostgreSQL to quickly find rows that match a query condition based on the values in multiple columns, which can […]

PostgreSQL indexing best practices

Don’t index every column If indexes are so useful, why don’t we add them to every column? There are a few good reasons, but a big one is that indexes add overhead to writes. Not only do indexes need to be kept up to date when we write to the table, but they can also […]