I'm using Gorm and have some questions as to how to retrieve nested SubComments from the model. The problem I'm getting is comments nested two levels deep, i.e. the Comment.SubComments are not loading. Am I missing something with the Preload?
I also think I need a composite foreign key on Comment of foreignKey:parent_id,parent_type but thats not working.
https://goplay.tools/snippet/kOhjUs7X6NQ
package main
import (
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type BlogPost struct {
ID uint `gorm:"primary_key"`
Content string
Comments []Comment `gorm:"foreignKey:parent_id;references:id"`
}
type ParentType int
const (
PT_BlogPost ParentType = 1
PT_Comment = 2
)
type Comment struct {
ID uint `gorm:"primary_key"`
ParentId uint
ParentType ParentType
Comment string
// TODO composite foreign key not working
SubComments []Comment `gorm:"foreignKey:parent_id,parent_type;references:id"`
}
func createComment(parentId uint, parentType ParentType) {
switch parentType {
case PT_BlogPost:
var blogPost BlogPost
// lookup blog post
if err := models.DB.Where("id = ?", parentId).First(&blogPost).Error; err != nil {
return
}
comment := Comment{
ParentId: parentId,
ParentType: PT_BlogPost,
Comment: "",
SubComments: nil,
}
models.DB.Create(&comment)
models.DB.Model(&blogPost).Updates(&BlogPost{
Comments: append(blogPost.Comments, comment),
})
case models.PT_Comment:
var parentComment Comment
// lookup comment
if err := models.DB.Where("id = ?", parentId).First(&parentComment).Error; err != nil {
return
}
// Create comment and add comment to db
comment := Comment{
ParentId: parentComment.ID,
ParentType: models.PT_Comment,
Comment: "",
SubComments: nil,
}
models.DB.Create(&comment)
// Append to Parent Comment and persist Parent Comment
models.DB.Session(&gorm.Session{FullSaveAssociations: true}).Model(&parentComment).Updates(&Comment{
SubComments: append(parentComment.SubComments, comment),
})
}
}
func GetCommentsForBlogPost(blogPostId uint) {
var comments []Comment
// Lookup Comments by BlogPostId
**// TODO Problem is it is not returning all nested comments**
**// i.e. The Comments.SubComments**
if err := models.DB.Preload(clause.Associations).
Where(&Comment{ParentType: PT_BlogPost, ParentId: blogPostId}).
Find(&comments).Error; err != nil {
return
}
}
Trying to create an index on ParentId and ParentType and setting that as the foreign key does not work either:
type Comment struct {
ID uint `gorm:"primary_key"`
ParentId uint `gorm:"index:idx_parent"`
ParentType ParentType `gorm:"index:idx_parent"`
Comment string
// TODO composite foreign key not working
SubComments []Comment `gorm:"foreignKey:idx_parent"`
}
I get an error on the commented line below:
invalid field found for struct Comment's field SubComments: define a valid foreign key for relations or implement the Valuer/Scanner interface
type CreateBlogPostInput struct {
Title string `json:"title" binding:"required"`
Content string `json:"content" binding:"required"`
}
func CreateBlogPost(input CreateBlogPostInput) {
var input CreateBlogPostInput
// Create blog post
blogPost := models.BlogPost{
Title: input.Title,
Content: input.Content,
Comments: []models.Comment{},
}
// ***Foreign key error here***
models.DB.Create(&blogPost)
}
Comment From: github-actions[bot]
This issue has been automatically marked as stale because it has been open 360 days with no activity. Remove stale label or comment or this will be closed in 180 days