使用类似的模型与gorm进行映射,但是gorm预加载是错误的

问题描述 投票:0回答:1

首先,我有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)
,这是错误的,请帮助我。

go go-gorm preload
1个回答
0
投票

预加载无法正常工作,因为它需要基本模型,它依赖于

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'
        )
© www.soinside.com 2019 - 2024. All rights reserved.