gormでのbulk update、いい方法ないか
まず、素晴らしい記事を見つけた。
mysqlで一括更新を行う際、ELTとFIELD関数を使えば、Bulk insertの時と同様に一回のsqlで実行できる。
これこそがbulk updateって感じの書き方。
insert on duplicate keyも、結局検証して追加か更新かを判定しているので、なかったら追加されてしまうという余計な潜在的ギミックを伴う。
純粋に更新だけしたいときに、ワンチャン追加もされるとなると、開発時の脳内メモリが消費される。
これをgormで実現したいが、可能なのか。
bulk insertの場合、すでに実装を行なっている人がいた。これを参考にできそう。
ただ、bulk insertはgormがすでに提供しているので、あくまでも参考に使える。
上記の記事的には、
追加したいデータのストラクト配列から「?」の部分に代入するための適切な配列を生成する
方針だった。良いと思う。ELT, FIELD関数の引数部分に代入できる配列を生成すれば実現できそう。
では、gormを動かせる環境を作りたい。
mysqlはローカルに作成してあるものに検証用のデータベースを用意した。
「gorm 使い方」と調べたときに、以下の記事が出てきた。
dbに接続する部分など、わざわざ調べて書いてくのはめんどくさすぎるので、この記事のを丸々使った。
「gorm db 接続 書き方」でググるのではなく、「gorm 使い方」で検索すれば、接続情報も書いてくれてる記事に出くわす可能性が高い。
勘が熟成してきたことを実感させる。
とりあえず一括更新ができれば良いので、上記の使い方の記事内のUserのストラクト配列もそのまま参考にしてinserts
reflectを使って、
userValue := reflect.ValueOf(user)
userType := reflect.TypeOf(user)
numField := userValue.NumField()
for i := 0; i < numField; i++ {
field := userType.Field(i)
fieldValue := userValue.Field(i).String()
fmt.Printf("%s = %s\n", field.Name, fieldValue)
}
こんな処理を書いた。
fieldValueのところを、names, ages, emails配列のようなstringスライスに振り分ける想定だった。
なんとそれはできなさそうだ。
なぜか。golangのプログラムでは
まず、やりたいことを整理してみる。
- 渡されたUsersスライスから、各フィールドごとに振り分けた配列が欲しい
- そのスライスがどのようなフィールドを持っているかに関係ない実装がしたい
copilotに聞いてみるか。