GORM-预付尽可能深的预紧力
我正在使用GORM,并有一些问题,即如何从模型中检索嵌套子额度
。我得到的问题是注释深嵌套了两个级别,即comment.subcomments
没有加载。我是否错过了preload
的东西?
我还认为我需要一个复合外键,以评论efirnekey:parent_id,parent_type
,但这是行不通的。
https://goplay.tool.tool.tool.tools/snippet/kohjus7x6nq
这是Asteriskdev的另一种尝试。
t支持SQLite DBS。
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
}
}
试图在parentid和parentype上创建索引,并将其设置为外键也不起作用:
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"`
}
我在下面的注释行上遇到错误: 为struct Comment的字段子节目找到的无效字段:定义关系的有效外国密钥或实现估价师/扫描仪界面
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)
}
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
Here is another attempt by asteriskdev:
https://goplay.tools/snippet/jUu_W8B4cg-
You will need to run the code locally as the playground doesn't support sqlite DBs.
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)
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
编辑:
这是我想到的,以使您朝着正确的方向前进。现在我已经坐了下来了,我不知道您想要的是您想要的。这取决于您需要在天气中深处有多少层次,它会开始变得笨拙。您不需要任何复合密钥,甚至不需要明确声明关系。使用GORM命名惯例编写的方式,可以推断这种关系。
使用Pure Go Sqlite驱动程序,并使用Logger
在
parthtype
上进行GORM进行GORM您的实现开关,因此我将其保留。您需要实时数据库连接。查看是否有一个并返回它,如果不是创建一个并将其返回。
因为
blogpost
具有注释[]注释
字段和注释
具有blog postid
field gorm侵蚀了关系。一个blogpost
可以拥有许多注释
一个注释
可以具有许多子注释
s。注释
可以具有一个blog postID,它指的是与之关联的博客文章。它也可以发表评论。 Gorm渗透了这种关系。 Gorm读取blogpostid
ASblogpost.id
。commentid
作为comment.id
。Toplevelid
将包含顶部注释
id
。如果注释
是顶级注释,toplevelid
将包含其自己的id
。这里的想法是每个注释
知道其顶级注释
'sid
。新的
blogpost
创建评论 的构造函数
在这里,您必须在更新之前保存,才能知道
注释>注释
的ID
是什么是设置toplevelcommentId
。此函数将与Blogpost
s或其他注释>注释>评论>评论>评论
s的关联 s,具体取决于其附属于哪个父。每个评论都知道其深度
。每次创建新的评论时,深度最高的注释都会添加到顶级注释
s深度
depth
用于确定的数量“。子表”
s要添加到preload()Gorm方法中。这些是将保存最终到数据库的方法。
创建
Blogpost
和7个嵌套注释
s。递归循环并打印出每个
注释
您找到的。当然,这只是一个例子,希望它有帮助。
完整源代码:
EDIT:
This is what I came up with to get you going in the right direction. Now that I've sat down with it, I don't know if preloading is what you want. It depends on how many levels deep you need to go weather it will start to get cumbersome or not. You don't need any composite keys or to even explicitly declare relationships. The way this is written, using GORM naming convention, the relationships are inferred.
Use the pure go sqlite driver and use a logger for GORM
Your implementation switches on
ParentType
so I kept it.You need a live database connection. Look to see if there is one and return it, if not create one and return it.
Because
BlogPost
has aComments []Comment
field andComment
has aBlogPostID
field GORM infers the relationship. OneBlogPost
can have manyComment
OneComment
can have many SubComment
s.A
Comment
can have a BlogPostID that refers to the BlogPost it is associated with. It can also have a CommentID. GORM infers the relationship. GORM readsBlogPostID
asBlogPost.ID
.CommentID
asComment.ID
. TheTopLevelID
will contain the top mostComment
ID
. If theComment
is the top levelComment
,TopLevelID
will contain its ownID
. The idea here is everyComment
knows its top levelComment
'sID
.Constructor for a new
BlogPost
Creating a comment
Here, you have to save before updating in order to know what the
ID
of theComment
is to setTopLevelCommentID
. This function will handle associatingComment
s withBlogPost
s or otherComment
s depending on which parent it is being attached to. Every comment knows itsDepth
. Every time a new comment is created, the comment with the highest depth is added to the top levelComment
sDepth
Depth
is used to determine the number of".SubComment"
s to add to the Preload() GORM method.These are methods to finalize the save to the database.
Create a
BlogPost
and 7 nestedComment
s.Loop over them recursively and print out every
Comment
you find.This of course is only an example, Hope it helps.
Full source code: