LoginSignup
7
7

More than 5 years have passed since last update.

逆引きgorm

Posted at

gormの使い方を自分向けにまとめました。適宜追加していきます。

基本的にこれがわかってたらなんとかなる。
そして大体公式ドキュメントに書いてあります!

以下のようなデータを用意して色々操作してみたいと思います。

# 初期状態
mysql> select * from persons;
+----+------+-----+-------+---------------------+---------------------+
| id | name | age | hobby | created_at          | updated_at          |
+----+------+-----+-------+---------------------+---------------------+
|  1 | A    |  20 | NULL  | 2018-10-04 11:13:35 | 2018-10-04 11:13:35 |
|  2 | B    |  30 | c     | 2018-10-04 11:13:35 | 2018-10-04 11:13:35 |
|  3 | C    |  15 | NULL  | 2018-10-04 11:13:35 | 2018-10-04 11:13:35 |
|  4 | D    |  44 | d     | 2018-10-04 11:13:35 | 2018-10-04 11:13:35 |
|  5 | E    |  60 | NULL  | 2018-10-04 11:13:35 | 2018-10-04 11:13:35 |
+----+------+-----+-------+---------------------+---------------------+
5 rows in set (0.00 sec)
// Go言語でのPeople定義
package main

import (
        "time"
)

type Person struct {
        Id        int `json:"id" gorm:"primary_key"`
        Name      string `json:"name"`
        Age       int `json:"age"`
        Hobby     string `json:"hobby"`
        CreatedAt time.Time `json:"createdAt" sql:"DEFAULT:current_timestamp"`
        UpdatedAt time.Time `json:"updatedAT" sql:"DEFAULT:current_timestamp on update current_timestamp"`
}

最初の1件を取得する

var person Person
db.First(&person)
fmt.Printf("%+v\n", person)

// 出力結果
//{Id:1 Name:A Age:20 Hobby: CreatedAt:2018-10-04 11:37:57 +0000 UTC UpdatedAt:2018-10-04 11:37:57 +0000 UTC}
// 実行SQL
// SELECT * FROM `people`   ORDER BY `people`.`id` ASC LIMIT 1

文字列検索をする

var people []Person
db.Where("name = ?", "B").Find(&people)
fmt.Printf("%+v\n", people)

// 出力結果
// [{Id:2 Name:B Age:30 Hobby:c CreatedAt:2018-10-04 11:37:57 +0000 UTC UpdatedAt:2018-10-04 11:37:57 +0000 UTC}]
// 実行SQL
//  SELECT * FROM `people`  WHERE (name = 'B')

並び替えをする

var people []Person
db.Order("age desc").Find(&people)
fmt.Printf("%+v\n", people)

// 出力結果
// [{Id:5 Name:E Age:60 Hobby: CreatedAt:2018-10-04 11:37:57 +0000 UTC UpdatedAt:2018-10-04 11:37:57 +0000 UTC}
// {Id:4 Name:D Age:44 Hobby:d CreatedAt:2018-10-04 11:37:57 +0000 UTC UpdatedAt:2018-10-04 11:37:57 +0000 UTC}
// {Id:2 Name:B Age:30 Hobby:c CreatedAt:2018-10-04 11:37:57 +0000 UTC UpdatedAt:2018-10-04 11:37:57 +0000 UTC}
// {Id:1 Name:A Age:20 Hobby: CreatedAt:2018-10-04 11:37:57 +0000 UTC UpdatedAt:2018-10-04 11:37:57 +0000 UTC}
// {Id:3 Name:C Age:15 Hobby: CreatedAt:2018-10-04 11:37:57 +0000 UTC UpdatedAt:2018-10-04 11:37:57 +0000 UTC}]
// 実行SQL
//  SELECT * FROM `people`   ORDER BY age desc

取得件数を絞り込む

var people []Person
db.Order("age desc").Limit(3).Offset(1).Find(&people)
fmt.Printf("%+v\n", people)

// 実行結果
// [{Id:4 Name:D Age:44 Hobby:d CreatedAt:2018-10-04 11:37:57 +0000 UTC UpdatedAt:2018-10-04 11:37:57 +0000 UTC}
// {Id:2 Name:B Age:30 Hobby:c CreatedAt:2018-10-04 11:37:57 +0000 UTC UpdatedAt:2018-10-04 11:37:57 +0000 UTC}
// {Id:1 Name:A Age:20 Hobby: CreatedAt:2018-10-04 11:37:57 +0000 UTC UpdatedAt:2018-10-04 11:37:57 +0000 UTC}]
// 実行SQL
// SELECT * FROM `people`   ORDER BY age desc LIMIT 3 OFFSET 1

データを登録する

f := Person{
         Name: "F",
         Age: 12,
     }
db.Create(&f)
fmt.Printf("%+v\n", f)

このとき、hobbyはなにも設定していなかったですが実際DBにはが入ります。

mysql> select id from people where id = 6 and hobby is null;
Empty set (0.00 sec)

mysql> select id from people where id = 6 and hobby = "";
+----+
| id |
+----+
|  6 |
+----+
1 row in set (0.00 sec)

NULLを入れるには、対象のカラムの型をポインタにします。

type Person struct {
        ~~~
        Hobby     *string `json:"hobby"`
        ~~~
}

最後上記の処理を実行すると

mysql> select id from people where id = 7 and hobby is null ;
+----+
| id |
+----+
|  7 |
+----+
1 row in set (0.00 sec)

NULLが入っているのがわかります。

データを更新する

person := Person{ Id: 1 }
db.Model(&person).Update("hobby", "a")
fmt.Printf("%+v\n", person)

// 実行結果
// {Id:1 Name: Age:0 Hobby:a CreatedAt:0001-01-01 00:00:00 +0000 UTC UpdatedAt:2018-10-04 21:26:56.983776665 +0900 JST m=+0.003486322}
// 実行SQL
// UPDATE `people` SET `hobby` = 'a', `updated_at` = '2018-10-04 21:26:56'  WHERE `people`.`id` = '1'

どうやらgormはUpdateのときはupdated_atに自動で値を入れてくれるみたいです。

実行後のレコード
mysql> select * from people where id = 1;
+----+------+-----+-------+---------------------+---------------------+
| id | name | age | hobby | created_at          | updated_at          |
+----+------+-----+-------+---------------------+---------------------+
|  1 | A    |  20 | a     | 2018-10-04 12:26:45 | 2018-10-04 12:26:57 |
+----+------+-----+-------+---------------------+---------------------+
1 row in set (0.00 sec)

nameやageはなにも設定してませんが、空になったりしませんでした。

意図して空にしてみたらどうなるんでしょうか?

person := Person{ Id: 1, Age: 0 }
db.Model(&person).Update(person)
fmt.Printf("%+v\n", person)

// 実行結果
// {Id:1 Name: Age:0 Hobby:<nil> CreatedAt:0001-01-01 00:00:00 +0000 UTC UpdatedAt:2018-10-04 23:40:35.479965986 +0900 JST m=+0.003397484}
// 実行SQL
// UPDATE `people` SET `id` = '1', `updated_at` = '2018-10-04 23:40:35'  WHERE `people`.`id` = '1'

うーん、このやり方だとうまく動きません。
structでのintの初期値は0であるため、gormが検知できないんですね。

person := Person{ Id: 1 }
data := map[string]interface{} {
            "age": 0,
        }
db.Model(&person).Update(data)
fmt.Printf("%+v\n", person)

// 実行結果
// {Id:1 Name: Age:0 Hobby:<nil> CreatedAt:0001-01-01 00:00:00 +0000 UTC UpdatedAt:2018-10-04 23:46:12.378224923 +0900 JST m=+0.003037641}
// 実行SQL
// UPDATE `people` SET `age` = '0', `updated_at` = '2018-10-04 23:46:12'  WHERE `people`.`id` = '1'

更新の際はStructを使うのではなく、mapを使うと意図した動きになりました。

データを削除する

person := Person{ Id: 5 }
db.Delete(&person)
// 実行SQL
// DELETE FROM `people`  WHERE `people`.`id` = '5'
7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7