【问题标题】:Creating GORM dynamic query with optional paramters使用可选参数创建 FORM 动态查询
【发布时间】:2021-07-05 16:44:14
【问题描述】:

我已经被一个 GORM 问题困扰了大约一整天。我需要能够根据以下 4 项中的任何一项过滤消息表:发件人、收件人、关键字和日期范围。它还必须分页。按发件人和收件人过滤正在工作,分页也是如此。到目前为止,这是我提出的查询,但它似乎不适用于日期范围或关键字。

这是我从 MySQL 中选择的方式

db.Preload("Thread").Where(query).Scopes(Paginate(r)).Find(&threadMessages)

我正在创建这样的查询:

var query map[string]interface{}

然后根据我传递的参数,我通过向地图添加新的键值来更新查询:

query = map[string]interface{}{"user_id": sender, "recipient_id": recipient}

如果我尝试这样的事情,它似乎不起作用:

query = map[string]interface{}{"created_at > ?": fromDate}

对于 LIKE 条件似乎也不起作用:

query = map[string]interface{}{"contents LIKE ?": keyword}

我选择这种方法的原因是我似乎无法获得可选输入来工作。因为它需要一个带有位置参数的字符串,而空位置参数似乎导致 MySQL 返回一个空数组。有没有其他人处理过这样复杂的 GORM 问题?任何帮助在这一点上表示赞赏。

【问题讨论】:

    标签: mysql go go-gorm


    【解决方案1】:

    map[string]interface{} 传递给Where() 似乎只适用于Equals 操作或IN 操作(如果提供了切片作为值)。

    实现您想要的一种方法是构造clause.Expression 的切片,并在需要时将子句附加到切片。然后,您可以简单地将所有子句(使用... 运算符传递整个切片)传入db.Clauses()

    clauses := make([]clause.Expression, 0)
    
    if mustFilterCreatedAt {
        clauses = append(clauses, clause.Gt{Column: "created_at", fromDate})
    }
    
    if mustFilterContents {
        clauses = append(clauses, clause.Like{Column: "contents", Value: keyword})
    }
    
    db.Preload("Thread").Clauses(clauses...).Scopes(Paginate(r)).Find(&threadMessages)
    

    注意:如果您尝试搜索包含keyword 的内容,则应将通配符% 连接到keyword 的末尾,否则LIKE 的行为与= 基本相同:

    clause.Like{Column: "contents", Value: "%" + keyword + "%"}
    

    【讨论】:

    • 谢谢。这似乎完成了我想做的事情。
    【解决方案2】:

    我对此的最终解决方案是根据从客户端发送的查询参数创建动态 Where 子句,如下所示:

        fields := []string{""}
        values := []interface{}{}
    

    例如,如果有关键字参数:

        fields = []string{"thread_messages.contents LIKE ?"}
        values = []interface{}{"%" + keyword + "%"}
    

    并在以下查询中使用动态子句:

    db.Preload("Thread", "agency_id = ?", agencyID).Preload("Thread.ThreadUsers", "agency_id = ?", agencyID).Joins("JOIN threads on thread_messages.thread_id = threads.id").Where("threads.agency_id = ?", agencyID).Where(strings.Join(fields, " AND "), values...).Scopes(PaginateMessages(r)).Find(&threadMessages)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-02
      • 2021-01-14
      • 2017-08-10
      • 2013-09-16
      • 2019-05-01
      • 2020-01-24
      • 2017-01-22
      • 2017-04-20
      相关资源
      最近更新 更多