GORM Golang の関連付け
Go では、GORM ORM を利用して、関連情報を持つ複数のエンティティをクエリするときに共通の課題が発生します。この問題を説明するために、例を詳しく見てみましょう。
町とそれに関連する場所を表す構造を考えます:
type Place struct { ID int Name string Town Town } type Town struct { ID int Name string }
次のサンプル データを含むデータベースを想定します:
places table | towns Table | |||||
---|---|---|---|---|---|---|
id | name | town_id | id | name | ||
1 | Place1 | 1 | 1 | Town1 | ||
2 | Place2 | 1 | 2 | Town2 |
すべての場所とそれに対応する町を取得するには、次のコマンドを試みます。クエリ:
db := gorm.Open("sqlite3", "./data.db") defer db.Close() places := []Place{} db.Find(&places)
ただし、結果は次のようになります:
[{1 Place1 {0 }} {2 Mares Place2 {0 }}]
対応する町の情報が欠落していることに注意してください。これを修正するには、Place 構造体の外部キーを TownID として指定する必要があります:
type Place struct { ID int Name string Description string TownID int Town Town }
期待される結果を得るには、次のアプローチを選択できます:
db.Find(&places) for i, _ := range places { db.Model(places[i]).Related(&places[i].Town) }
これにより確かに望ましい結果が得られますが、場所ごとに追加のデータベース クエリがトリガーされるため、n 1 問題に悩まされます。
Aより効率的なソリューションには、プリロードの利用が含まれます。
db.Preload("Town").Find(&places)
この簡潔なアプローチにより、次の最適化されたデータベース クエリが生成されます。
SELECT * FROM "places" [0.92ms] SELECT * FROM "towns" WHERE ("id" in ('1'))
プリロードを利用することで、関連する町の情報が確実に取得されます。単一のデータベース クエリにより、パフォーマンスが最適化され、n 1 の問題が排除されます。
以上がGORM で関連エンティティを効率的にクエリするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。