Gorm Golang orm 协会 [英] Gorm Golang orm associations

查看:16
本文介绍了Gorm Golang orm 协会的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将 Go 与 GORM ORM 一起使用.我有以下结构.关系很简单.一个镇有多个地方,一个地方属于一个镇.

I'm using Go with the GORM ORM. I have the following structs. The relation is simple. One Town has multiple Places and one Place belongs to one Town.

type Place struct {
  ID          int
  Name        string
  Town        Town
}

type Town struct {
  ID   int
  Name string
}

现在我想查询所有地方并与他们的所有领域相处相应城镇的信息.这是我的代码:

Now i want to query all places and get along with all their fields the info of the corresponding town. This is my code:

db, _ := gorm.Open("sqlite3", "./data.db")
defer db.Close()

places := []Place{}
db.Find(&places)
fmt.Println(places)

我的示例数据库有以下数据:

My sample database has this data:

/* places table */
id  name    town_id
 1  Place1        1
 2  Place2        1

/* towns Table */
id name
 1 Town1
 2 Town2

收到这个:

[{1 Place1 {0 }} {2 Mares Place2 {0 }}]

但我期待收到这样的东西(两个地方都属于同一个城镇):

But i'm expecting to receive something like this (both places belongs to the same town):

[{1 Place1 {1 Town1}} {2 Mares Place2 {1 Town1}}]

我怎么做这样的查询?我尝试使用 PreloadsRelated 没有成功(可能是错误的方式).我无法获得预期的结果.

How can i do such query ? I tried using Preloads and Related without success (probably the wrong way). I can't get working the expected result.

推荐答案

TownID 必须指定为外键.Place 结构是这样的:

TownID must be specified as the foreign key. The Place struct gets like this:

type Place struct {
  ID          int
  Name        string
  Description string
  TownID      int
  Town        Town
}

现在有不同的方法来处理这个问题.例如:

Now there are different approach to handle this. For example:

places := []Place{}
db.Find(&places)
for i, _ := range places {
    db.Model(places[i]).Related(&places[i].Town)
}

这肯定会产生预期的结果,但请注意日志输出和触发的查询.

This will certainly produce the expected result, but notice the log output and the queries triggered.

[4.76ms]  SELECT  * FROM "places"
[1.00ms]  SELECT  * FROM "towns"  WHERE ("id" = '1')
[0.73ms]  SELECT  * FROM "towns"  WHERE ("id" = '1')

[{1 Place1  {1 Town1} 1} {2 Place2  {1 Town1} 1}]

输出是预期的,但这种方法有一个基本缺陷,请注意,对于每个地方都需要进行另一个 db 查询,这会产生 n + 1 问题.这可以解决问题,但随着场所数量的增加,很快就会失控.

The output is the expected but this approach has a fundamental flaw, notice that for every place there is the need to do another db query which produce a n + 1 problem issue. This could solve the problem but will quickly gets out of control as the amount of places grow.

事实证明,使用预加载的好的方法相当简单.

It turns out that the good approach is fairly simple using preloads.

db.Preload("Town").Find(&places)

就是这样,产生的查询日志是:

That's it, the query log produced is:

[22.24ms]  SELECT  * FROM "places"
[0.92ms]  SELECT  * FROM "towns"  WHERE ("id" in ('1'))

[{1 Place1  {1 Town1} 1} {2 Place2  {1 Town1} 1}]

这种方法只会触发两个查询,一个针对所有地点,一个针对所有拥有地点的城镇.这种方法在地方和城镇的数量方面可以很好地扩展(在所有情况下只有两个查询).

This approach will only trigger two queries, one for all places, and one for all towns that has places. This approach scales well regarding of the amount of places and towns (only two queries in all cases).

这篇关于Gorm Golang orm 协会的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆