如何合并查询

时间:2019-03-11 19:53:55

标签: go go-gorm

我正在写一个页面,其中呈现了分页的Blog帖子列表。我在Go 1.12中使用GORM。 每个博客文章都有一个名为“用户”的作者,该用户可以在必要时包含一些其他员工信息。 (例如简介,函数标题等)

我的模特:

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合并? 我想像手动查询一样对它们进行优化。

1 个答案:

答案 0 :(得分:0)

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

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