ORM框架Gorm-Many To Many

多对多关联

定义博客标签结构体

// 博客文章
type Blog struct {
	gorm.Model
	Name    string
	Content string `gorm:"type:text"`
	Tags    []Tag  `gorm:"many2many:blog_tags"`
}

// 标签结构体
type Tag struct {
	gorm.Model
	Name string
	Blog []Blog `gorm:"many2many:blog_tags"`
}

连接数据库并初始化数据库

var db *gorm.DB

func init() {
	dsn := "root:root@tcp(127.0.0.1:3306)/go_orm?charset=utf8mb4&parseTime=True&loc=Local"
	d, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		log.Fatal(err)
	}
	db = d
	db.AutoMigrate(&Blog{}, &Tag{})
}

添加模拟标签数据

// 创建测试标签
func CreateTags() {
	var tags = []Tag{
		{Name: "php"},
		{Name: "go"},
		{Name: "html"},
		{Name: "js"},
		{Name: "bootstrap"},
		{Name: "mysql"},
	}
	d := db.Create(tags)
	fmt.Printf("d.RowsAffected: %v\n", d.RowsAffected)
}

创建模拟博客数据

func CreateBlogTags() {
	var tags []Tag
	db.Model(&Tag{}).Find(&tags)
	for _, tag := range tags {
		fmt.Printf("tag.ID: %v--tag.Name: %v\n", tag.ID, tag.Name)
	}
	var blogs = []Blog{
		{Name: "blog1", Content: "blog1-blog2", Tags: []Tag{tags[0], tags[1]}},
		{Name: "blog2", Content: "blog2-blog2", Tags: []Tag{tags[2], tags[3], tags[4]}},
		{Name: "blog3", Content: "blog3-blog3", Tags: []Tag{tags[0], tags[2], tags[5]}},
	}
	d := db.Create(blogs)
	fmt.Printf("d.RowsAffected: %v\n", d.RowsAffected)
}

数据库表数据如下

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

预加载

查询所有博客并查询出对应下的标签
func testSelect1() {
	var blogs []Blog
	db.Preload("Tags").Find(&blogs)

	for _, blog := range blogs {
		fmt.Printf("blog.Name: %v\n", blog.Name)
		var tagsName []string
		for _, v := range blog.Tags {
			tagsName = append(tagsName, v.Name)
		}
		fmt.Printf("tagsName: %v\n", tagsName)
	}
	fmt.Println("----------------------------------------------")
}
查询所有标签并查询出对应的博客
func testSelect2() {
	var tags []Tag
	db.Preload("Blog").Find(&tags)
	for _, tag := range tags {
		fmt.Printf("tag.Name: %v\n", tag.Name)
		var blogsId []uint
		for _, v := range tag.Blog {
			blogsId = append(blogsId, v.ID)
		}
		fmt.Printf("blogsId: %v\n", blogsId)
	}
	fmt.Println("----------------------------------------------")
}

运行结果如下
在这里插入图片描述

嵌套预加载

查询所有博客以及博客下的标签,而且也要查到标签下面的所有博客,类似做相关性推荐

func testSelect3() {
	var blogs []Blog
	db.Preload("Tags.Blog").Find(&blogs)
	for _, blog := range blogs {
		fmt.Printf("blog.Name: %v\n", blog.Name)
		var tagsName []string
		for _, v := range blog.Tags {
			tagsName = append(tagsName, v.Name)
			var blogsId []uint
			for _, v1 := range v.Blog {
				blogsId = append(blogsId, v1.ID)
			}
			fmt.Printf("blogsId: %v\n", blogsId)

		}
		fmt.Printf("tagsName: %v\n", tagsName)
	}
	fmt.Println("----------------------------------------------")
}

在这里插入图片描述

添加关联

为博客在原有基础上添加新的标签

func addBlogTag() {
	var tags []Tag
	db.Model(&Tag{}).Find(&tags)
	var blog Blog
	db.Model(&Blog{}).Where("id", 1).Find(&blog)
	// 原来已有1 2标签
	db.Model(&blog).Association("Tags").Append([]Tag{tags[2], tags[3]})
}

运行结果后新增了3 4标签id,因为切片下标原因上面写的2,3
在这里插入图片描述

替换关联

把博客原有的标签替换为新的,相当于做博客更新

func replaceBLogTag() {
	var tags []Tag
	db.Model(&Tag{}).Find(&tags)
	var blog Blog
	db.Model(&Blog{}).Where("id", 1).Find(&blog)
	// 原来已有1 2 3 4标签
	db.Model(&blog).Association("Tags").Replace([]Tag{tags[4], tags[1]})

}

运行结果后只剩下2,5标签id
在这里插入图片描述

关联计数

查询具体博客有几个标签
查询具体标签有几个博客再用
查询所有标签分别有几个博客再用

func countBlogTag() {
	var blog Blog
	db.Model(&Blog{}).Where("id", 1).Find(&blog)
	i := db.Model(&blog).Association("Tags").Count()
	fmt.Printf("i: %v\n", i)
	fmt.Println("-----------------------------------------------")
}

func countTagBlog() {
	var tag Tag
	db.Model(&Tag{}).Where("id", 1).Find(&tag)
	i := db.Model(&tag).Association("Blog").Count()
	fmt.Printf("i: %v\n", i)
	fmt.Println("-----------------------------------------------")
}

func countAllTagBlog() {
	var tags []Tag
	db.Model(&Tag{}).Find(&tags)
	for _, tag := range tags {
		i := db.Model(&tag).Association("Blog").Count()
		fmt.Printf("tag.Name: %v--count:%v\n", tag.Name, i)
	}
}

运行结果如下
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值