Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
Go

08 Advanced Query dengan GORM di Golang

· 5 mnt baca ·Ihsan Arif

Pelajari berbagai teknik query tingkat lanjut di GORM dengan Golang, termasuk Smart Select Fields, Locking, SubQuery, From SubQuery, dan lainnya. Dilengkapi contoh kode dan unit test.

Dalam artikel ini, kita akan membahas berbagai teknik query tingkat lanjut menggunakan GORM di Golang. Topik-topik yang dibahas meliputi Smart Select Fields, Locking, SubQuery, From SubQuery, Group Conditions, IN with multiple columns, Named Argument, Find To Map, FirstOrInit, FirstOrCreate, Optimizer/Index Hints, Iteration, FindInBatches, Query Hooks, Pluck, Scopes, dan Count.


1. Smart Select Fields

Metode Select() digunakan untuk memilih field tertentu dalam query agar lebih efisien.

Contoh Kode Fungsi

go
1func GetUserNames(db *gorm.DB) ([]string, error) {
2    var names []string
3    result := db.Model(&User{}).Select("name").Pluck("name", &names)
4    return names, result.Error
5}

Penjelasan Kode

  1. db.Model(&User{}) → Menentukan model User sebagai sumber data.
  2. .Select("name").Pluck("name", &names) → Memilih hanya kolom name dan menyimpannya dalam slice names.
  3. return names, result.Error → Mengembalikan daftar nama dan error jika ada.

Unit Test

go
1func TestGetUserNames(t *testing.T) {
2    names, err := GetUserNames(db)
3    assert.Nil(t, err)
4    assert.Greater(t, len(names), 0)
5}

Penjelasan Unit Test

  1. Memanggil GetUserNames(db) untuk mendapatkan daftar nama user.
  2. Memastikan tidak ada error dengan assert.Nil(t, err).
  3. Memastikan jumlah nama yang dikembalikan lebih dari nol dengan assert.Greater(t, len(names), 0).

2. Locking

Metode Locking digunakan untuk mengunci record agar tidak diubah oleh transaksi lain selama proses berlangsung.

Contoh Kode Fungsi

go
1func LockUserRecord(db *gorm.DB, id uint) (*User, error) {
2    var user User
3    result := db.Clauses(clause.Locking{Strength: "UPDATE"}).First(&user, id)
4    return &user, result.Error
5}

Penjelasan Kode

  1. db.Clauses(clause.Locking{Strength: "UPDATE"}) → Menambahkan klausa locking pada query.
  2. .First(&user, id) → Mengambil record user berdasarkan id.
  3. return &user, result.Error → Mengembalikan user yang ditemukan dan error jika ada.

Unit Test

go
1func TestLockUserRecord(t *testing.T) {
2    user, err := LockUserRecord(db, 1)
3    assert.Nil(t, err)
4    assert.NotNil(t, user)
5}

Penjelasan Unit Test

  1. Memanggil LockUserRecord(db, 1) untuk mengunci user dengan ID 1.
  2. Memastikan tidak ada error dengan assert.Nil(t, err).
  3. Memastikan user yang dikembalikan tidak nil dengan assert.NotNil(t, user).

3. SubQuery

Metode SubQuery digunakan untuk menyusun query dalam query utama, biasanya digunakan untuk filtering yang kompleks.

Contoh Kode Fungsi

go
1func GetLatestUsers(db *gorm.DB) ([]User, error) {
2    var users []User
3    subQuery := db.Model(&User{}).Select("MAX(created_at)").Group("id")
4    result := db.Where("created_at IN (?)", subQuery).Find(&users)
5    return users, result.Error
6}

Penjelasan Kode

  1. subQuery := db.Model(&User{}).Select("MAX(created_at)").Group("id") → Membuat subquery untuk mendapatkan waktu pembuatan terbaru.
  2. db.Where("created_at IN (?)", subQuery).Find(&users) → Mengambil user dengan created_at terbaru dari subquery.
  3. return users, result.Error → Mengembalikan hasil query dan error jika ada.

Unit Test

go
1func TestGetLatestUsers(t *testing.T) {
2    users, err := GetLatestUsers(db)
3    assert.Nil(t, err)
4    assert.Greater(t, len(users), 0)
5}

Penjelasan Unit Test

  1. Memanggil GetLatestUsers(db) untuk mendapatkan daftar user terbaru.
  2. Memastikan tidak ada error dengan assert.Nil(t, err).
  3. Memastikan jumlah user yang dikembalikan lebih dari nol dengan assert.Greater(t, len(users), 0).

4. From SubQuery

Metode From SubQuery digunakan untuk menyusun query berdasarkan hasil dari subquery lain yang dijalankan sebelumnya.

Contoh Kode Fungsi

go
1func GetUsersFromSubQuery(db *gorm.DB) ([]User, error) {
2    var users []User
3    subQuery := db.Model(&User{}).Select("id").Where("age > ?", 25)
4    result := db.Where("id IN (?)", subQuery).Find(&users)
5    return users, result.Error
6}

Penjelasan Kode

  1. subQuery := db.Model(&User{}).Select("id").Where("age > ?", 25) → Membuat subquery untuk mendapatkan ID user dengan usia di atas 25 tahun.
  2. db.Where("id IN (?)", subQuery).Find(&users) → Mengambil user berdasarkan ID yang didapat dari subquery.
  3. return users, result.Error → Mengembalikan daftar user dan error jika ada.

Unit Test

go
1func TestGetUsersFromSubQuery(t *testing.T) {
2    users, err := GetUsersFromSubQuery(db)
3    assert.Nil(t, err)
4    assert.Greater(t, len(users), 0)
5}

Penjelasan Unit Test

  1. Memanggil fungsi GetUsersFromSubQuery(db) untuk mendapatkan daftar user.
  2. Memastikan tidak ada error dengan assert.Nil(t, err).
  3. Memastikan jumlah user lebih dari nol dengan assert.Greater(t, len(users), 0).

5. Group Conditions

Metode Group By digunakan untuk mengelompokkan hasil berdasarkan suatu kolom tertentu.

Contoh Kode Fungsi

go
1func GetUserCountGroupedByAge(db *gorm.DB) ([]map[string]interface{}, error) {
2    var results []map[string]interface{}
3    result := db.Model(&User{}).
4        Select("age, count(*) as total").
5        Group("age").
6        Find(&results)
7    return results, result.Error
8}

Unit Test

go
1func TestGetUserCountGroupedByAge(t *testing.T) {
2    results, err := GetUserCountGroupedByAge(db)
3    assert.Nil(t, err)
4    assert.Greater(t, len(results), 0)
5}

6. IN with Multiple Columns

Metode ini digunakan untuk melakukan query dengan kondisi IN pada lebih dari satu kolom.

Contoh Kode Fungsi

go
1func GetUsersWithMultiColumnCondition(db *gorm.DB) ([]User, error) {
2    var users []User
3    result := db.Where("(name, age) IN ((?, ?), (?, ?))", "Alice", 30, "Bob", 25).Find(&users)
4    return users, result.Error
5}

Unit Test

go
1func TestGetUsersWithMultiColumnCondition(t *testing.T) {
2    users, err := GetUsersWithMultiColumnCondition(db)
3    assert.Nil(t, err)
4    assert.Greater(t, len(users), 0)
5}

7. Named Argument

Metode Named Argument digunakan untuk mempermudah pembacaan query dengan parameter yang memiliki nama.

Contoh Kode Fungsi

go
1func GetUsersByNamedParams(db *gorm.DB, name string, age int) ([]User, error) {
2    var users []User
3    result := db.Where("name = @name AND age = @age", map[string]interface{}{ "name": name, "age": age }).Find(&users)
4    return users, result.Error
5}

Unit Test

go
1func TestGetUsersByNamedParams(t *testing.T) {
2    users, err := GetUsersByNamedParams(db, "Alice", 30)
3    assert.Nil(t, err)
4    assert.Greater(t, len(users), 0)
5}

Selanjutnya, kita akan membahas Find To Map, FirstOrInit, FirstOrCreate, Optimizer/Index Hints, Iteration, FindInBatches, Query Hooks, Pluck, Scopes, dan Count.

Untuk mempelajari lebih lanjut tentang database dalam Golang, silakan kunjungi:


IH
Ihsan Arif
Backend engineer & penulis di Santekno. Aktif menulis tentang Go, Laravel, dan arsitektur backend modern.
Follow

💬 Komentar