はじめに
普段の開発でORMにGormを採用しているのですが、クエリー結果を構造体へ詰めるために、First
、Take
、Find
のどれを使えばいいのかついつい忘れちゃうことがありました。また、条件に合うレコードが見つからなかった場合にTake
はエラーを返した気がするけど、Find
はどうだっけ...ともなっていたので、今回備忘録がてらまとめてみました。
結論
単体オブジェクトを取得したい場合は、Take
, First
, Last
を使い、複数オブジェクトを取得したい場合は、Find
, Scan
を使う。
First
, Take
, Last
は条件に合うレコードが存在しなかった場合、ErrRecordNotFound
を返却するが、Find
, Scan
は何も返さない。
Find
, Scan
は単体オブジェクトに対しても使用可能です。
db.Limit(1).Find(&user)
とすることで、Take
と同様のSQLが流れますが、エラーは返りません。
以下で詳しく説明していきます。
First
First
はprimary keyでorderして条件に合う最初のレコードを返却します。
また、レコードが見つからない場合は、ErrRecordNotFound
を返却します。
db.Where("name = ?", "jinzhu").First(&user)
//=> SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;
Take
Take
はorderせずランダムに1レコードを取得します。
また、レコードが見つからない場合は、ErrRecordNotFound
を返却します
db.Where("name = ?", "jinzhu").First(&user)
//=> SELECT * FROM users WHERE name = 'jinzhu' LIMIT 1;
Last
Last
はprimary keyで逆順にorderして条件に合う最後のレコードを返却します。また、レコードが見つからない場合は、ErrRecordNotFoundを返却します。
db.Where("name = ?", "jinzhu").Last(&user)
//=> SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id DESC LIMIT 1;
Find
Find
は条件に合うすべてのレコードを取得します。単体オブジェクトに対しても使用可能で、エラーは返りません。
db.Where("name = ?", "jinzhu").Find(&users)
//=> SELECT * FROM users WHERE name = 'jinzhu';
単体オブジェクトに対して使用する場合は、db.Limit(1).Find(&user)
のようにします。この場合、条件に合うレコードが存在しなくてもエラーは返らず、空のオブジェクトが返されます。
Scan
Scan
は条件に合うすべてのレコードを取得し、特定のフィールドのみを構造体にマッピングします。通常はクエリの結果を別の構造体へマッピングするために使用されます。単体オブジェクトに対しても使用可能で、エラーは返りません。
type Result struct {
Name string
Age int
}
var result Result
db.Table("users").Select("name, age").Where("name = ?", "jinzhu").Scan(&result)
//=> SELECT name, age FROM users WHERE name = 'jinzhu';
終わりに
Gormは公式ドキュメントが豊富で、日本語版も充実しているのでよかったら読んでみてください。