如何在GORM中仅在关联不存在时创建关联?

huangapple go评论85阅读模式
英文:

How to create association only if it doesn't exist? (GORM)

问题

我正在遍历一个字符串数组,只有在该属性不存在时才创建一个具有该属性的文档:

(dbi:我的 GORM 数据库实例)

var postTags []models.Tag

for _, tagSlug := range tagsArray {
	tag := models.Tag{
		Slug: tagSlug,
	}

	err = dbi.Where("slug = ?", tagSlug).FirstOrCreate(&tag).Error
	if err != nil {
	        return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
		        "error": "Internal Server Error",
	        })
	}
	postTags = append(postTags, tag)
}

然后使用这些标签创建一个帖子:

post := models.Post{
       ...,
       Tags: postTags 
}

dbi.Create(&post)

模型:

type Post struct {
	BaseModel
	Title string `json:"title"`
	MarkdownUploadURL string `json:"markdownUploadUrl"` 
	AuthorID string `json:"authorId"`
	Tags []Tag `json:"tags" gorm:"many2many:posts_tags"`
}

type Tag struct {
	BaseModel
	Slug string `json:"slug"`
}

我尝试过:将 dbi.FirstOrCreate() 更改为 dbi.First(),然后检查 errors.Is(err, gorm.ErrRecordNotFound)

但是,每次调用该函数时,即使它们已经存在于数据库中,我都会得到具有不同 ID 的不同标签...

英文:

I am looping through an array of strings to create an document with that property ONLY if it doesn't exist:

(dbi: my GORM database instance)

var postTags []models.Tag

for _, tagSlug := range tagsArray {
	tag := models.Tag{
		Slug: tagSlug,
	}

	err = dbi.Where("slug = ?", tagSlug).FirstOrCreate(&tag).Error
	if err != nil {
	        return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
		        "error": "Internal Server Error",
	        })
	}
	postTags = append(postTags, tag)
}

And then Creating a post with those tags:

post := models.Post{
       ...,
       Tags: postTags 
}]

dbi.Create(&post)

Models:

type Post struct {
	BaseModel
	Title string `json:"title"`
	MarkdownUploadURL string `json:"markdownUploadUrl"` 
	AuthorID string `json:"authorId"`
	Tags []Tag `json:"tags" gorm:"many2many:posts_tags"`
}

type Tag struct {
	BaseModel
	Slug string `json:"slug"`
}

I tried: Changing dbi.FirstOrCreate() for dbi.First() and then checking if errors.Is(err, gorm.ErrRecordNotFound

But every time The function is called I get different Tags with different IDs, even if they already exist in the database...

答案1

得分: 0

据我理解,你可以以更精确和高效的方式实现你的目标。

  • 在迭代tagsArray时,将主键(很可能是在你的BaseModel中)添加到你的标签中。
  • 然后,将缺失的标签放入帖子中,而不是在数据库中创建它。
  • 然后创建帖子(默认情况下,它将更新关联)。由于你在标签中提供了ID,这将与现有的ID冲突,并将使用先前的值进行更新(实际上什么也不做),否则将作为新标签插入,以防该ID没有对应的行。
var postTags []models.Tag

for _, tagSlug := range tagsArray {
    tag := models.Tag{
        ID: models.BaseModel{ ID: tagSlug.ID},
        Slug: tagSlug,
    }
    postTags = append(postTags, tag)
}

post := models.Post{
       ...,
       Tags: postTags 
}

dbi.Create(&post)

请注意,这只是代码的一部分,可能需要根据你的实际情况进行适当的调整。

英文:

As far as I understand you can achieve your target in a more precise and efficient way.

  • Add primary key (most probably in your BaseModel) to your tag when iterating tagsArray.
  • Then instead of creating the absent tags in db put it in post.
  • Then create the Post (By default it will upsert associations). As you're giving ID in tag this will conflict with existing ID and will do update with previous values (essentially doing nothing) otherwise insert as new tag in case no row present for that ID.
var postTags []models.Tag

for _, tagSlug := range tagsArray {
    tag := models.Tag{
        ID: models.BaseModel{ ID: tagSlug.ID},
        Slug: tagSlug,
    }
    postTags = append(postTags, tag)
}

post := models.Post{
       ...,
       Tags: postTags 
}]

dbi.Create(&post)

答案2

得分: 0

修复了。不是在帖子中添加标签,而是像这样进行操作:

post := models.Post{
       Tags: postTags, 
}

dbi.Create(&post)

我是这样做的:

post := models.Post {
        // 其他字段 (AuthorID, MarkdownUploadURL, Title)
}

dbi.Create(&post)

dbi.Model(&post).Omit("Tags.*").Association("Tags").Append(postTags)

参考链接:https://github.com/go-gorm/gorm/issues/3605

英文:

Fixed it. Instead of addding the tags in the post, like so:

post := models.Post{
       Tags: postTags, 
}

dbi.Create(&post)

I did it like this:

post := models.Post {
        // Other fields (AuthorID, MarkdownUploadURL, Title)
}

dbi.Create(&post)

dbi.Model(&post).Omit("Tags.*").Association("Tags").Append(postTags)

reference: https://github.com/go-gorm/gorm/issues/3605

huangapple
  • 本文由 发表于 2023年1月21日 05:23:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75189439.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定