有条件地构建查询,并保留公共部分以执行不同的操作。

huangapple go评论85阅读模式
英文:

Build query conditionally and keeping the common part to execute differently

问题

尝试弄清楚如何使用gorm有条件地构建查询,并保存常见的查询部分并执行它。

假设我正在查询课程列表,如下所示。

common_query_part := app.GetDB(). // <= 这返回*gorm.DB
Model(&models.Course{}).
Where("status=?", models.CourseStatusPublished) //models.CourseStatusPublished是一个常量

现在,我想获取已发布课程的列表,并获取其数量。所以我尝试了以下方法。

published_course_count := *common_query_part

然后对于课程列表

result := common_query_part.
Offset(offset).
Limit(limit).
find(&courses)

if result.Error != nil {
//处理错误
}

对于计数

result = published_course_count.Count(&total)

if result.Error != nil {
//处理错误
}

第一部分完美地工作。但是查询的第二部分不起作用,也不会生成任何错误。在这种情况下我该怎么办?常见的查询部分可能非常庞大和复杂。因此,为了获取计数而重新编写它可能容易出错。所以是否有一种方法可以保留常见的查询部分,并且有时执行它以获取已发布的课程,有时执行它以获取已发布课程的计数?

英文:

Trying to figure out how can I build query conditionally using gorm, save the common query part and execute it.

Suppose I am querying list of courses like below.

common_query_part := app.GetDB(). // &lt;= this returns *gorm.DB
		Model(&amp;models.Course{}).
		Where(&quot;status=?&quot;, models.CourseStatusPublished) //models.CourseStatusPublished is a constant

Now I would like to get the list of published courses. And also get its count. So I tried it like so.

published_course_count := *common_query_part

and then for the course list

   result := common_query_part.
                 Offset(offset).
                 Limit(limit).
                 find(&amp;courses)
   
       if result.Error !=nil {
         //handle error
       } 

and for the count

result = published_course_count.Count(&amp;total)
       
if result.Error !=nil {
             //handle error
           } 

The first part works perfectly. But second part of the query does not work, nor even generate any error. What should I do in this case? The common query part can be huge and complex. So rewriting it again just for getting the count can be error prone. So is there a way where I will keep the common query part and execute it sometimes for published courses.. sometimes for published courses count?

答案1

得分: 1

我不认为GORM打算让你以这种方式重用查询。很难确定,但最有可能不起作用的原因是仍然存在一些共享的状态。

这行代码:published_course_count := *common_query_partgorm.DB结构体进行了按值复制,但如果该结构体包含任何指针(它确实包含指针),那么这些指针也会被复制,导致两个指向相同对象的结构体仍然“链接”在一起。你需要一个专门的克隆函数,gorm中确实存在这样的函数,但没有公开。

我建议你将公共部分的生成放在一个函数中,并调用两次,这样你就不必复制粘贴相同的查询。

func common_query_part() *gorm.DB {
    return app.GetDB().
        Model(&models.Course{}).
        Where("status=?", models.CourseStatusPublished)
}
英文:

I don't believe GORM intends you to reuse your query that way. It is hard to say definitively but it most likely doesn't work because there is some state that is still shared.

This: published_course_count := *common_query_part does a copy by value of the gorm.DB struct, but if that struct contain any pointers(it does) then those are copied as well resulting in two separate struct with pointer to the same objects and thus still being "linked". You need a dedicated clone function, which does exist in gorm but is not exposed.

I would advise you to put the generation of the common part inside a function and call it twice, that way you don't have to copy-paste the same query.

func common_query_part() *gorm.DB {
    return app.GetDB().
        Model(&amp;models.Course{}).
        Where(&quot;status=?&quot;, models.CourseStatusPublished)
}

huangapple
  • 本文由 发表于 2021年11月5日 00:37:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/69842758.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定