如何有条件地搜索与 gorm 具有多对多关系的数据

How to conditionally search data with many to many relationships with gorm

我正在开发一个使用 gorm 管理报价的应用程序。 报价有多个标签。 当指定多个标签时,我想获取包含所有指定标签的报价。

这是我的数据模型。

type Quote struct {
    ID        uint      `gorm:"primary_key" json:"id"`
    CreatedAt time.Time `json:"created_at"`
    UpdatedAt time.Time `json:"updated_at"`
    Text      string    `json:"text"`
    Page      uint      `json:"page"`
    ISBN      string    `json:"isbn"`
    Tags      []Tag     `gorm:"many2many:quote_tags;" json:"tags"`
}

type Tag struct {
    ID        uint      `gorm:"primary_key" json:"id"`
    CreatedAt time.Time `json:"created_at"`
    Name      string    `json:"name"`
}

我想做这样的事情。 (语法不正确)

db.Preload("Tags").Where(<quotes.tags.name contains all tagNames>).Find(&quotes) // tagNames []string

有没有办法用 gorm 做到这一点? 提前谢谢你。

在这种情况下,您需要做的是首先找出您 SQL 需要 运行 需要的样子。

要获得与所有给定标签匹配的所有引号,您需要将引号 table 连接到一个子查询,该子查询计算每个引号匹配的标签数量,如下所示:

SELECT * 
FROM quotes 
JOIN (
   SELECT quote_id, count(*) AS count
   FROM quote_tags qt JOIN tags t ON qt.tag_id = t.id
   WHERE t.name IN ('tag1', 'tag2', 'tag4')
   GROUP BY quote_id
) AS matched ON quote_id = quotes.id AND matched.count = 3

一旦你有了它,你就试着在 Gorm 中这样说:

requiredTags := []string{"tag1", "tag2", "tag3"}
db.Preload("Tags").
    Joins(
        "JOIN (?) AS matched ON quote_id = quotes.id AND matched.count = ?",
        db.Select("quote_id, count(*) AS count").
            Table("quote_tags qt").
            Joins("JOIN tags t ON qt.tag_id = t.id").
            Where("t.name IN (?)", requiredTags).
            Group("quote_id"),
        len(requiredTags),
    ).
    Find(&quotes)

参见:GORM Advanced Query/From Subquery