【问题标题】:How to join two tables in GORM如何在 GORM 中连接两个表
【发布时间】:2021-07-10 10:30:24
【问题描述】:

我有两张桌子,

SET search_path = public;


CREATE TABLE IF NOT EXISTS changelog
(
    id          BIGINT NOT NULL PRIMARY KEY,
    object_type TEXT,
    object_id   BIGINT,
    parent_type TEXT,
    parent_id   BIGINT,
    action      TEXT,
    field       TEXT,
    old_value   TEXT,
    new_value   TEXT,
    comment_id  INTEGER,
    created_on  TIMESTAMP WITHOUT TIME ZONE,
    created_by  BIGINT
);

CREATE TABLE IF NOT EXISTS changelog_comments
(
    id         INTEGER NOT NULL PRIMARY KEY,
    comment    TEXT,
    created_on TIMESTAMP WITHOUT TIME ZONE,
    created_by BIGINT
);

SET search_path = DEFAULT;

我想为返回字段的更改日志实现搜索方法

"objectType"
"objectId"
"parentType"
"parentId"
"action"
"field"
"oldValue"
"newValue"
"comment"
"createdBy"
"createdOn"

如您所见,结果来自两个表的连接。

我找到了https://gorm.io/docs/preload.html,但老实说,我不明白如何才能实现我的需要。

我认为以下内容可能会有所帮助

type ChangelogResponseItem struct {
    ObjectType string     `json:"objectType"`
    ObjectID   uuid.UUID  `json:"objectId"`
    ParentType string     `json:"parentType"`
    ParentID   uuid.UUID  `json:"parentId"`
    Action     string     `json:"action"`
    Field      *string    `json:"field"`
    OldValue   *string    `json:"oldValue"`
    NewValue   *string    `json:"newValue"`
    Comment    *string    `json:"comment"`
    CreatedBy  *uint64    `json:"createdBy"`
    CreatedOn  *time.Time `json:"createdOn"`
}

问题是如何从 GORM 中提到的表格中得到我提到的内容?

【问题讨论】:

    标签: go go-gorm


    【解决方案1】:

    一种方法是结合JoinsSelect 方法来获得你想要的。根据您的表格,它看起来像这样:

    list := []ChangelogResponseItem{}
    tx := db.Table("changelog").
             Joins("INNER JOIN changelog_comments cc ON cc.id = changelog.comment_id").
             Select("changelog.objectType, changelog.object_type, changelog.object_id, changelog.parent_type, changelog.parent_id, changelog.action, changelog.field, changelog.old_value, changelog.new_value, cc.comment, changelog.created_on, changelog.created_by").
             Find(&list)
    if tx.Error != nil {
      // handle error
    }
    

    这只是为了返回数据,搜索将包括额外的Where 方法。

    编辑:

    带有预加载选项的解决方案:

    结构:

    type ChangelogComment struct {
      ID uint64 `json:"id"`
      Comment string `json:"comment"`
    }
    
    type Changelog struct {
        ObjectType string     `json:"objectType"`
        ObjectID   uuid.UUID  `json:"objectId"`
        ParentType string     `json:"parentType"`
        ParentID   uuid.UUID  `json:"parentId"`
        Action     string     `json:"action"`
        Field      *string    `json:"field"`
        OldValue   *string    `json:"oldValue"`
        NewValue   *string    `json:"newValue"`
        CommentID    uint64    `json:"comment_id"`
        Comment    *ChangelogComment `json:"comment"` 
        CreatedBy  *uint64    `json:"createdBy"`
        CreatedOn  *time.Time `json:"createdOn"`
    }
    

    使用Preload 方法的代码:

    list := []Changelog{}
    tx := db.Preload("Comment").Find(&list)
    if tx.Error != nil {
      // handle error
    }
    

    请注意,在这种情况下,您将拥有一个不同的 JSON 对象,该对象的结构不会是扁平的,因为您还将拥有一个 comment 字段。

    【讨论】:

    • 感谢您的关注和回答。一个问题,我们如何跳过select 语句并提供一种更好的方式来返回获取数据?这可能吗?
    • 我不确定它是否可以,因为您的 ChangelogResponseItem 结构基本上是一个使用多个表的自定义视图。如果它没有 Comment 字段,你可以在没有 Select 方法的情况下完成它。另外,你可以这样写Select("changelog.*, cc.comment")
    • 谢谢你的快速,你能帮我吗? (请提供支持我需要的结构,我可以重新定义结构以使查询更简单。)?
    • 我的意思是,最后我想以这种方式返回响应,但是我们怎样才能使它更容易呢?
    • 我添加了一个带有 Preload 选项和一些结构修改的解决方案
    猜你喜欢
    • 2022-01-12
    • 1970-01-01
    • 2021-05-06
    • 2020-05-11
    • 2018-11-08
    • 2021-11-20
    • 2018-02-19
    • 2014-03-24
    • 1970-01-01
    相关资源
    最近更新 更多