GORM many2many关系表的创建和查询
2020-03-27 本文已影响0人
_敏讷
最近在用golang搭建个人博客的后台,数据库选用了gorm + mySQL的组合,其中文章(articles
)和标签(tags
)两个表是多对多的关系,由于对数据库不是很熟悉,外加gorm的文档较为简略,在这里踩了很多的坑。现在在这篇文章中总结下实现的方法。
第一步:定义gorm表的struct
type Article struct {
gorm.Model
Title string `gorm:"not null"`
Content string `gorm:"not null"`
Tags []Tag `gorm:"many2many:tag_articles"`
}
type Tag struct {
TagId string `gorm:"primary_key"`
TagName string `gorm:"unique;not null"`
Articles []Article `gorm:"many2many:tag_articles"`
}
第二步:连接数据库,创建表
func InitDB() *gorm.DB {
//创建一个数据库的连接
var err error
db, err := gorm.Open("mysql","root:071918@tcp(127.0.0.1:3306)/blog?charset=utf8")
if err != nil {
panic(err)
}
// 调用该语句会自动生成联结表tag_articles
db.AutoMigrate(&Article{}, &Tag{})
return db
}
第三步:存数据
tag1 := Tag{ TagId: "001", TagName: "React" }
db.Save(&tag1)
article := Article{
Title: "Redux进阶教程",
Content: "正文内容",
// 子项中的数据必须是保存过或者查找出的数据(即数据库已有的数据)
Tags: []Tag {
tag1,
},
}
或者
tagIdList := ["001", "002"]
var tags []db.Tag
// 分别查询tagIdList,并将结果插入tags列表
for i := range tagIdList {
tag := db.Tag{}
DB.Where("tag_id = ?", tagIdList[i]).First(&tag)
tags = append(tags, tag)
}
articleModel := db.Article{
Title: "这是标题",
Content: "这是正文",
Tags: tags,
}
// 保存
err := DB.Save(&articleModel)
在上述步骤中有需要注意的是,Tags对应的数组项必须事先存入数据库,或者事先查找过,否则仅会生成article的记录,不会生成tag_articles联结表的记录。
第四步:查询
因为不熟悉gorm的API,有一部分查询是使用基本的sql语句查询的,性能方面可能不太好,但是作为个人博客后端使用问题不大。
查询带标签(Tag
)子项的文章(Article
)列表
var articleList []Article
err := DB.Preload("Tags").Find(&articleList)
fmt.Println(articleList)
查询带文章数(Count
)的标签(Tag
)列表
// 定义所需的struct
type tagResult struct {
Count int
TagName string
TagId string
}
var tagList []tagResult
err := DB.Raw("SELECT COUNT(*) count, t.tag_name, t.tag_id " +
// 下面这句使用笛卡尔积连接两个表,复杂度变成了m * n,性能较差
"FROM tag_articles ta, tags t " +
"WHERE t.tag_id=ta.tag_tag_id " +
"GROUP BY ta.tag_tag_id ").Scan(&tagList)
fmt.Println(tagList)
根据标签(TagId
)查询全部文章列表
// 定义所需的struct
type articleResult struct {
Title string
ArticleId string
}
var articleList []articleResult
tagId := "001"
// 查询语句
err := DB.Raw("SELECT a.title, a.article_id "+
// 下面这句使用笛卡尔积连接两个表,复杂度变成了m * n,性能较差
"FROM tag_articles ta, articles a "+
"WHERE a.article_id=ta.article_article_id "+
"AND ta.tag_tag_id= ? ", tagId).Scan(&articleList)
fmt.Println(articleList)