gorm查询多对多关联的数量

2025-04-10T15:37:00

下面给出两种常见的做法,关键在于如何统计某个标签被多少篇文章引用:

方法一:使用 Join Table 直接查询统计

假设你的多对多关系存储在 article_tags 表中,并且标签模型(Tag)类似如下:

type Tag struct {
    ID   uint   `gorm:"primaryKey"`
    Name string
    // 其他字段...
}

那么在删除文章时,你可以通过查询 article_tags 表来统计当前标签是否被其他文章引用:

func DeletePost(uid string) error {
    var article Article
    db := sql.GetDB()

    // 预加载 Tags, 这样后续能遍历对应的标签
    if err := db.Where("uid = ?", uid).Preload("Tags").First(&article).Error; err != nil {
        return err
    }
    
    // 遍历每个标签,检查是否还存在其他文章关联
    for _, tag := range article.Tags {
        var count int64
        // 查询 join table 中该 tag 被其他文章引用的次数
        // 请确保 "article_tags" 为你实际使用的表名
        db.Table("article_tags").Where("tag_id = ?", tag.ID).Count(&count)
        if count == 1 {
            // 如果仅有一个关联,则删除该标签
            if err := db.Delete(&tag).Error; err != nil {
                return err
            }
        }
    }

    // 移除关联(删除 join table 中对应记录)
    if err := db.Model(&article).Association("Tags").Clear(); err != nil {
        return err
    }

    // 删除文章记录
    if err := db.Delete(&article).Error; err != nil {
        return err
    }
    return nil
}

方法二:借助 GORM Association Mode 的 Count 方法

如果你在标签的模型中也定义了与文章的关联(比如在 Tag 模型中加入 Articles []Article gorm:"many2many:article_tags;"`),你就可以利用 GORM 内置的 Association("Articles").Count()` 来查询关联数量。示例如下:

标签模型:

type Tag struct {
    ID       uint      `gorm:"primaryKey"`
    Name     string
    Articles []Article `gorm:"many2many:article_tags;"`
}

在删除文章的函数中:

func DeletePost(uid string) error {
    var article Article
    db := sql.GetDB()

    // 预加载 Tags,确保能遍历所有标签
    if err := db.Where("uid = ?", uid).Preload("Tags").First(&article).Error; err != nil {
        return err
    }

    // 先清除文章与标签的关联关系
    if err := db.Model(&article).Association("Tags").Clear(); err != nil {
        return err
    }

        // 检查每个标签是否已经没有文章关联,如果是则删除标签
    for _, tag := range article.Tags {
        // 使用 Association Mode 的 Count 方法
        count := db.Model(&tag).Association("Articles").Count()
        if count == 1 {
            if err := db.Delete(&tag).Error; err != nil {
                return err
            }
        }
    }
    
    // 删除文章记录
    if err := db.Delete(&article).Error; err != nil {
        return err
    }
    return nil
}

总结

  • 查询统计方式:可以直接根据 join table(如 article_tags)进行查询统计,代码简单直观,不需要在 Tag 模型中额外定义关联。
  • Association Count 方式:需要在 Tag 模型中定义反向的多对多关联,但借助 GORM 的 Association().Count() 方法,代码更加面向对象,调用简单。

两种方法各有优劣,可以根据你的项目情况(模型定义是否包含双向关联、代码风格偏好等)来选择。

当前页面是本站的「Baidu MIP」版。发表评论请点击:完整版 »