首先,我有Post模型,它已经迁移到数据库了
type Post struct {
ID uuid.UUID `gorm:"type:uuid;default:uuid_generate_v4();primary_key"`
UserId uuid.UUID `gorm:"type:uuid;not null"`
User User `gorm:"foreignKey:UserId;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
ParentId *uuid.UUID `gorm:"type:uuid;default:null"`
ParentPost *Post `gorm:"foreignKey:ParentId;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Content string `gorm:"type:text;not null"`
}
接下来,我有一个类似的模型,但有一个附加字段 isLiked,该模型不会迁移,仅用于从 Post 模型映射到
type PostWithLiked struct {
ID uuid.UUID `gorm:"type:uuid;default:uuid_generate_v4();primary_key"`
UserId uuid.UUID `gorm:"type:uuid;not null"`
User User `gorm:"foreignKey:UserId;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
ParentId *uuid.UUID `gorm:"type:uuid;default:null"`
ParentPost *Post `gorm:"foreignKey:ParentId;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Content string `gorm:"type:text;not null"`
IsLiked bool
}
这是执行查询的函数
func (r *rPost) GetOne(
ctx context.Context,
id uuid.UUID,
authenticatedUserId uuid.UUID,
) (*entities.PostWithLiked, error) {
var postModel models.PostWithLiked
if err := r.db.WithContext(ctx).
Model(&models.Post{}).
Select(`posts.*,
EXISTS (
SELECT 1
FROM like_user_posts
WHERE like_user_posts.post_id = posts.id AND like_user_posts.user_id = ?
) AS is_liked
`, authenticatedUserId).
Where("posts.id = ?", id).
Preload("User").
Preload("ParentPost.User").
First(&postModel).
Error; err != nil {
return nil, err
}
return mapper.FromPostWithLikedModel(&postModel), nil
}
这是查询结果
[56.799ms] [rows:0] SELECT * FROM "posts" WHERE "posts"."parent_id" = '354fd551-96f0-4899-a7d7-e38ef524636f' AND "posts"."deleted_at" IS NULL
[56.020ms] [rows:1] SELECT * FROM "users" WHERE "users"."id" = '129f1a32-ad18-49f1-b989-b6cd4c243e30' AND "users"."deleted_at" IS NULL
[469.482ms] [rows:1] SELECT posts.*,
EXISTS (
SELECT 1
FROM like_user_posts
WHERE like_user_posts.post_id = posts.id AND like_user_posts.user_id = '7dfdf978-9706-4720-aa3f-382af4b14f70'
) AS is_liked
FROM "posts" WHERE posts.id = '354fd551-96f0-4899-a7d7-e38ef524636f' AND "posts"."deleted_at" IS NULL ORDER BY "posts"."id" LIMIT 1
ParentPost预加载错误,实际上帖子的parent_id是6d591d06-80ee-4cf3-9695-e1eb986d7885,但它把帖子id放入354fd551-96f0-4899-a7d7-e38ef524636f来执行预加载
当我进行映射时
First(&models.Post)
父帖子已正确预加载,但是当我使用PostWithLiked模型时,预加载parentPost使用原始帖子的id而不是parent_id
但是什么时候使用
First(&models.PostWithLiked)
,这是错误的,请帮助我。
预加载无法正常工作,因为它需要基本模型,它依赖于
Model
上的关系,并将基于这些关系构建查询。当您使用其他结构(如 PostWithLiked
)时,它会感到困惑。
这按预期工作:
type Post struct {
ID uuid.UUID `gorm:"type:uuid;default:uuid_generate_v4();primary_key"`
UserId uuid.UUID `gorm:"type:uuid;not null"`
User User `gorm:"foreignKey:UserId;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
ParentId *uuid.UUID `gorm:"type:uuid;default:null"`
ParentPost *Post `gorm:"foreignKey:ParentId;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Content string `gorm:"type:text;not null"`
}
type PostWithLiked struct {
Post
IsLiked bool
}
func (r *rPost) GetOne(
ctx context.Context,
id uuid.UUID,
authenticatedUserId uuid.UUID,
) (*PostWithLiked, error) {
var (
post Post
postModel PostWithLiked
isLiked bool
)
if err := r.db.WithContext(ctx).
Model(&Post{}).
Where("posts.id = ?", id).
Preload("User").
Preload("ParentPost.User").
First(&post).
Error; err != nil {
return nil, err
}
if err := r.db.Raw(`
SELECT EXISTS (
SELECT 1
FROM like_user_posts
WHERE like_user_posts.post_id = ? AND like_user_posts.user_id = ?
)`, post.ID, authenticatedUserId).Scan(&isLiked).Error; err != nil {
return nil, err
}
postModel = PostWithLiked{
Post: post,
IsLiked: isLiked,
}
return &postModel, nil
}
以下是处理的查询:
[1.092ms] [rows:1] SELECT * FROM "users" WHERE "users"."id" = '571ee693-ffab-48a5-b098-3b270693cbea'
[2.146ms] [rows:1] SELECT * FROM "posts" WHERE "posts"."id" = '68cec1d2-b8ab-4966-aabe-94ac82b00902'
[0.347ms] [rows:1] SELECT * FROM "users" WHERE "users"."id" = '571ee693-ffab-48a5-b098-3b270693cbea'
[3.708ms] [rows:1] SELECT * FROM "posts" WHERE posts.id = '5a7b9b46-17ab-4851-a94e-0ea92c639d1e' ORDER BY "posts"."id" LIMIT 1
[0.568ms] [rows:1]
SELECT EXISTS (
SELECT 1
FROM like_user_posts
WHERE like_user_posts.post_id = '5a7b9b46-17ab-4851-a94e-0ea92c639d1e' AND like_user_posts.user_id = '571ee693-ffab-48a5-b098-3b270693cbea'
)