如何(预加载)在自定义列上加入 table?

How (preloading) join table on custom column?

假设我们有以下模型:

type Company struct {
    gorm.Model
    Name string
    Addresses []Address
}

type Address struct {
    gorm.Model
    CompanyID uint64
    Street string
    City string
    Country string
}

我想获取在特定位置有地址的所有公司(及其地址)。像这样:

SELECT company.*, address.* FROM company
INNER JOIN address ON address.company_id = company.id AND address.country = 'Bulgaria'

因此,如果一家公司在特定位置没有地址,我根本不会得到它。我正在尝试这样的事情:

db.Joins("Addresses", "addresses.country = ?", "Bulgaria").Find(&companies)

然而,它不起作用,因为 GORM 不接受连接的第二个参数(当使用预加载连接时),所以我应该检查生成的查询并做类似的事情:

db.Where(`"Address".country = ?`, "Bulgaria").Joins("Addresses").Find(&companies)

有没有更好的way/not hacky 方法?请记住,以上所有代码都是对实际问题的模拟,我不想暴露原始问题 models/queries.

您可以使用 PreloadAddresses 加载到 Company 对象中。

根据您描述的条件,如果您不想加载不符合您筛选条件的公司,您应该使用 INNER JOIN

两个选项:

首先,如果您的 table 被命名为 company,那么您的查询应该如下所示:

db.Table("company").
   Preload("Addresses").
   Joins("INNER JOIN addresses a ON a.company_id = company.id").
   Where("a.country = ?", "Bulgaria").
   Find(&companies)

其次,如果您的 table 被命名为 companies,那么您应该试试这个:

db.Preload("Addresses").
   Joins("INNER JOIN addresses a ON a.company_id = companies.id").
   Where("a.country = ?", "Bulgaria").
   Find(&companies)

如果您使用的是 Gorm v2,您可以通过 associations:

对一对多和一对多执行 CRUD 操作
var companies []Company
var addresses []Address
countries := []string{"Bulgaria"}
db.Model(&Address).Where("country IN (?)", countries).Find(&addresses)

// The key is using the previously fetched variable as the model for the association query 
db.Model(&addresses).Association("CompanyID").Find(&companies)

这也适用于多对多关系。

比较 Gorm 与原始 SQL 查询 (db.Raw(SQLquery)) 时,您通常会看到性能下降。从好的方面来说,您不必处理在 Go 中构建原始 sql 字符串所增加的复杂性,这非常好。我个人在我的项目中结合使用原始查询和 gorm 构建的查询:)