go - 如何合并查询

标签 go go-gorm

我正在编写一个页面,其中呈现了一个带有分页的博客文章列表。我在 Go 1.12 中使用 GORM。 每篇博文都有一个名为 User 的作者,如果需要,该用户可以包含一些额外的员工信息。 (例如介绍、功能标题……)

我的模型:

type EmployeeInfo struct {
    UserID    uint   `gorm:"not null;unique"`
    Title     string `gorm:"not null"`
    Intro     string `gorm:""`
}

type User struct {
    gorm.Model

    Username  string    `gorm:"unique;not null"`
    Password  string    `gorm:"unique;not null"`

    FirstName string    `gorm:"not null"`
    LastName  string    `gorm:"not null"`

    Company   Company   `gorm:"not null"`

    Role      string    `gorm:"not null;default:user"`
}

type BlogPost struct {
    gorm.Model

    Title     string    `gorm:"not null"`
    Slug      string    `gorm:"unique;not null;index"`
    Intro     string    `gorm:"not null"`
    Text      string    `gorm:"not null"`
    Category  string    `gorm:"not null"`
    PictureUrl string   `gorm:"not null"`
    Author    User      `gorm:"not null"`
    AuthorID  uint      `gorm:"not null"`
}

我的代码目前看起来像这样:

func (hh *BlogIndexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // set desired language
    language.SetLanguage(r)

    // set title
    hh.data.Title = fmt.Sprintf(
        "%s - %s",
        language.Translate("blog", nil, false),
        language.Translate("product", nil, false),
    )

    // get current page
    hh.data.Page = 0
    if intPage, err := strconv.Atoi(r.URL.Query().Get(pageQueryName)); err != nil && intPage >= 0 {
        hh.data.Page = intPage
    }

    // get max page number
    hh.data.MaxPage = 1
    var totalPosts int
    if err := hh.database.Model(&models.BlogPost{}).Count(&totalPosts).Error; err != nil {
        totalPosts = 1
    } else {
        hh.data.MaxPage = roundUp(float64(totalPosts / PostsPerPage))
    }

    // if page > maxPage, set it right
    if hh.data.Page > hh.data.MaxPage {
        hh.data.Page = hh.data.MaxPage
    }

    // fetch blog posts
    if err := hh.database.
        Preload("Author").
        Order("created_at DESC").
        Offset(PostsPerPage * hh.data.Page).
        Limit(PostsPerPage).
        Find(&hh.data.Posts).
        Error; err != nil {

        log.Errorf(appengine.NewContext(r), "could not get posts: %v", err)
    }

    // set cacheable
    system.SetCacheable(w, system.CacheTime1Day)

    // send webpage
    hh.template.Render("blog/index", w, hh.data)
}

但是,一个请求会触发 3 个不同的查询:

[2019-03-11 19:51:52]  [29.55ms]  SELECT count(*) FROM "blog_posts"  WHERE "blog_posts"."deleted_at" IS NULL
[0 rows affected or returned ]

[2019-03-11 19:51:52]  [27.50ms]  SELECT * FROM "blog_posts"  WHERE "blog_posts"."deleted_at" IS NULL ORDER BY created_at DESC LIMIT 9 OFFSET 0
[1 rows affected or returned ]

[2019-03-11 19:51:52]  [49.86ms]  SELECT * FROM "users"  WHERE "users"."deleted_at" IS NULL AND (("id" IN ('58')))

有没有办法将它们与 GORM 合并? 我想优化这些,就像手动查询一样。

最佳答案

GORM 在Preload 上不支持数据库级别的JOIN。您有两个选择:

  • 要么使用 Preload 并接受它执行额外查询以获取相关数据的事实(除非您的服务器负载很重,否则这应该不是问题)
  • 或者你可以自己写Raw Sql使用 JOIN 查询并在一个查询中处理所有内容,然后将数据映射到一个结构。

关于go - 如何合并查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55109392/

相关文章:

go - 将对象 slice 与引用对象一起填充

go - 是否可以将结构的 slice 作为接口(interface)传递给方法?

Golang 导入包

time - 在 golang TCP 中禁用截止日期

bash - 以编程方式执行到 docker 容器中

go - 编写具有多个可选参数的 API 端点

postgresql - 在gorm中获取结构中的嵌套对象

go - 高并发下Go `net/http`的一些困惑

postgresql - 事务执行后停留在pg_stat_activity状态

go - Gorm Extra,其中1 <> 1 in many2many