如何(预加载)在自定义列上加入 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.
您可以使用 Preload
将 Addresses
加载到 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 构建的查询:)
假设我们有以下模型:
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.
您可以使用 Preload
将 Addresses
加载到 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 构建的查询:)