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

09 Advance Query Data Gorm Library (Bagian 1)

· 5 mnt baca ·Ihsan Arif

Pelajari teknik query lanjutan di GORM dengan Golang, termasuk From SubQuery, Group Conditions, Named Arguments, IN with multiple columns, dan lainnya, lengkap dengan contoh kode dan unit test.

Artikel ini merupakan lanjutan dari pembahasan sebelumnya tentang Advanced Query dengan GORM. Kali ini, kita akan melanjutkan dengan teknik lanjutan lainnya seperti Find To Map, FirstOrInit, FirstOrCreate, Optimizer/Index Hints, Iteration, lengkap dengan contoh kode dan unit test.


8. Find To Map

Metode Find To Map digunakan untuk mengambil hasil query dan memetakannya ke dalam struktur data berbasis map. Ini berguna ketika kita ingin bekerja dengan hasil query dalam format yang lebih fleksibel.

Fungsi

go
1func GetUsersAsMap(db *gorm.DB) ([]map[string]interface{}, error) {
2    var results []map[string]interface{} // Deklarasi slice untuk menyimpan hasil query dalam format map
3    result := db.Model(&User{}).Find(&results) // Mengambil semua data dari tabel User dan menyimpannya ke dalam map
4    return results, result.Error // Mengembalikan hasil query dan error jika ada
5}

Penjelasan Kode

  1. var results []map[string]interface{} → Deklarasi slice untuk menyimpan hasil query dalam format map.
  2. db.Model(&User{}).Find(&results) → Mengambil semua data dari tabel User dan menyimpannya dalam map.
  3. return results, result.Error → Mengembalikan hasil query dan error jika ada.

Unit Test

go
 1func TestGetUsersAsMap_Success(t *testing.T) {
 2    results, err := GetUsersAsMap(db) // Memanggil fungsi untuk mendapatkan data user dalam format map
 3    assert.Nil(t, err) // Memastikan tidak ada error dalam query
 4    assert.Greater(t, len(results), 0) // Memastikan hasil query tidak kosong
 5}
 6
 7func TestGetUsersAsMap_Error(t *testing.T) {
 8    db, _ := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) // Membuka database tanpa tabel User
 9    results, err := GetUsersAsMap(db)
10    assert.NotNil(t, err) // Memastikan terjadi error karena tabel tidak ditemukan
11    assert.Equal(t, 0, len(results)) // Memastikan hasil query kosong
12}

Penjelasan Unit Test

  1. Memanggil GetUsersAsMap(db) untuk mendapatkan data dalam format map.
  2. Memastikan tidak ada error dengan assert.Nil(t, err).
  3. Memastikan hasil query tidak kosong dengan assert.Greater(t, len(results), 0).
  4. Menguji skenario error dengan database tanpa tabel User untuk memastikan error terjadi.

9. FirstOrInit

Metode FirstOrInit digunakan untuk mencari data dalam database. Jika data tidak ditemukan, maka struct akan diinisialisasi dengan nilai yang diberikan.

Fungsi

go
1func FirstOrInitUser(db *gorm.DB, name string) User {
2    var user User // Deklarasi variabel user
3    db.Where("name = ?", name).FirstOrInit(&user, User{Name: name}) // Jika user tidak ditemukan, inisialisasi struct User dengan nama yang diberikan
4    return user // Mengembalikan user yang ditemukan atau diinisialisasi
5}

Penjelasan Kode

  1. var user User → Deklarasi variabel user sebagai struct User.
  2. db.Where("name = ?", name).FirstOrInit(&user, User{Name: name}) → Mencari user dengan name yang diberikan. Jika tidak ditemukan, menginisialisasi struct User dengan nilai default.
  3. return user → Mengembalikan user yang ditemukan atau diinisialisasi.

Unit Test

go
1func TestFirstOrInitUser_Success(t *testing.T) {
2    user := FirstOrInitUser(db, "Alice")
3    assert.Equal(t, "Alice", user.Name)
4}
5
6func TestFirstOrInitUser_NewUser(t *testing.T) {
7    user := FirstOrInitUser(db, "Charlie")
8    assert.Equal(t, "Charlie", user.Name)
9}

Penjelasan Unit Test

  1. Memanggil FirstOrInitUser(db, "Alice") untuk mencari atau menginisialisasi user.
  2. Memastikan nama user sesuai dengan yang diharapkan menggunakan assert.Equal(t, "Alice", user.Name).
  3. Memastikan bahwa jika user tidak ditemukan, user baru akan diinisialisasi dengan nama yang diberikan.

10. FirstOrCreate

Metode FirstOrCreate digunakan untuk mencari data dalam database dan membuatnya jika tidak ditemukan.

Fungsi

go
1func FirstOrCreateUser(db *gorm.DB, name string) User {
2    var user User // Deklarasi variabel user
3    db.Where("name = ?", name).FirstOrCreate(&user, User{Name: name}) // Jika user tidak ditemukan, buat user baru dengan nama yang diberikan
4    return user // Mengembalikan user yang ditemukan atau dibuat
5}

Penjelasan Kode

  1. var user User → Deklarasi variabel user sebagai struct User.
  2. db.Where("name = ?", name).FirstOrCreate(&user, User{Name: name}) → Mencari user berdasarkan name, jika tidak ditemukan, membuat user baru dengan name yang diberikan.
  3. return user → Mengembalikan user yang ditemukan atau dibuat.

Unit Test

go
1func TestFirstOrCreateUser_Success(t *testing.T) {
2    user := FirstOrCreateUser(db, "Bob")
3    assert.Equal(t, "Bob", user.Name)
4}
5
6func TestFirstOrCreateUser_NewUser(t *testing.T) {
7    user := FirstOrCreateUser(db, "David")
8    assert.Equal(t, "David", user.Name)
9}

Penjelasan Unit Test

  1. Memanggil FirstOrCreateUser(db, "Bob") untuk mencari atau membuat user baru.
  2. Memastikan bahwa jika user ditemukan, user yang ada akan dikembalikan.
  3. Memastikan bahwa jika user tidak ditemukan, user baru akan dibuat dengan nama yang diberikan.

11. Optimizer/Index Hints

Metode ini digunakan untuk mengoptimalkan performa query dengan memberikan petunjuk kepada database mengenai indeks yang harus digunakan.

Fungsi

go
1func GetUsersWithIndexHint(db *gorm.DB) ([]User, error) {
2    var users []User // Deklarasi slice untuk menampung hasil query
3    result := db.Raw("SELECT * FROM users USE INDEX (idx_name)").Scan(&users) // Menjalankan query dengan hint penggunaan indeks tertentu
4    return users, result.Error // Mengembalikan hasil query dan error jika ada
5}

Penjelasan Kode

  1. var users []User → Deklarasi slice untuk menyimpan hasil query.
  2. db.Raw("SELECT * FROM users USE INDEX (idx_name)").Scan(&users) → Menjalankan query dengan petunjuk penggunaan indeks tertentu.
  3. return users, result.Error → Mengembalikan hasil query dan error jika ada.

Unit Test

go
1func TestGetUsersWithIndexHint_Success(t *testing.T) {
2    users, err := GetUsersWithIndexHint(db)
3    assert.Nil(t, err)
4}

12. Iteration

Metode ini digunakan untuk menelusuri data dalam bentuk batch kecil untuk mengurangi penggunaan memori.

Fungsi

go
 1func IterateUsers(db *gorm.DB) error {
 2    rows, err := db.Model(&User{}).Rows() // Mengambil semua baris data user dalam bentuk iterator
 3    if err != nil {
 4        return err
 5    }
 6    defer rows.Close() // Menutup iterasi setelah selesai digunakan
 7    for rows.Next() {
 8        var user User // Deklarasi variabel untuk menampung hasil scan
 9        db.ScanRows(rows, &user) // Memindai hasil dari iterator ke struct User
10    }
11    return nil
12}

Penjelasan Kode

  1. rows, err := db.Model(&User{}).Rows() → Mengambil semua baris data user dalam bentuk iterator.
  2. defer rows.Close() → Menutup iterasi setelah selesai digunakan untuk menghindari kebocoran memori.
  3. for rows.Next() → Melakukan iterasi pada setiap baris hasil query.
  4. var user User → Deklarasi variabel untuk menampung hasil scan.
  5. db.ScanRows(rows, &user) → Memindai hasil dari iterator ke struct User.

Unit Test

go
1func TestIterateUsers_Success(t *testing.T) {
2    err := IterateUsers(db)
3    assert.Nil(t, err)
4}

Lanjutkan membaca untuk pembahasan FindInBatches, Query Hooks, Pluck, Scopes, dan Count.

Untuk informasi lebih lanjut, kunjungi:


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

💬 Komentar