Count 方法这里怎么会多出一个 and 条件,导致结果不正确呢,我代码有问题么?
go 新手 求指点
代码片段
package util
type Result struct {
Code uint `json:"code"`
Data interface{} `json:"data"`
}
// NewResult creates a result with Code=0, Msg="", Data=nil.
func NewResult() *Result {
return &Result{
Code: 200,
Data: nil,
}
}
type JobRequestParam struct {
ID []uint `form:"id" binding:"required"`
OpsID uint `form:"ops_id" binding:"required"`
RunTime string `form:"run_time"`
}
package service
import (
"OpsSimon/util"
"log"
"sync"
)
// AssetsService 资产对象
type AssetsService struct {
mutex *sync.Mutex
}
// Assets 资产实例
var Assets = &AssetsService{
mutex: &sync.Mutex{},
}
// GetList 列表查询
func (srv *AssetsService) GetList(result interface{}, id []uint) (total int) {
err := db.Where(id).Find(result).Count(&total).Error
if err != nil {
log.Println(err.Error())
}
return total
}
func doJob(c *gin.Context) {
result := util.NewResult()
defer c.JSON( http.StatusOK, result)
var arg util.JobRequestParam
err := c.BindJSON(&arg)
if err != nil {
result.Code = http.StatusBadRequest
result.Data = err.Error()
return
}
log.Println(arg.ID)
log.Println(arg.OpsID)
log.Println("len:", len(arg.ID))
var host model.AssetsHosts
total := service.Assets.GetList(&host, arg.ID)
log.Println("total:", total)
if total != len(arg.ID) {
result.Code = http.StatusNotFound
result.Data = "Some host not found!"
return
}
}
1
seaguest 2019-09-04 19:10:44 +08:00
建议提问题的时候简明扼要一点,这里无关的东西太多了。
我的印象中 Find,和 Count 应该分开用吧,你这样想一下查两个值应该有点问题。 开一下 orm 的 log,测试两下不就出来了么。 |
2
seaguest 2019-09-04 19:15:07 +08:00
验证了一下,这么用也是对的,gorm 拆分成两个 sql 语句了。
问题应该在与你的 db 对象,前面已经加了条件了。 |
3
JimmyTinsley 2019-09-04 19:23:55 +08:00 via Android
红框里的应该是 Where(id)这一句导致的吧
|
5
Ansen OP |
6
ZSeptember 2019-09-04 22:14:54 +08:00
把 SQL 打印一下,看看。
|
7
Ansen OP @ZSeptember #6 图里面有,然后我再贴一下多出 and 的那条语句
```sql SELECT count(*) FROM `ops_assets_hosts` WHERE `ops_assets_hosts`.`deleted_at` IS NULL AND `ops_assets_hosts`.`id` = 3 AND ((`ops_assets_hosts`.`id` IN (1,2,3))) ``` |
8
JimmyTinsley 2019-09-05 09:25:31 +08:00 1
@Ansen #5 用 goland 帮你 debug 了一下
如果按照你的写法 `db.Where(id).Find(result).Count(&total).Error` 会产生两次 sql 查询, 就像你日志里面打印的两条一样. Find(result)这个方法本身会 `select * from xxx where xxx in xxx` 查询一遍结果, 然后当你链式调用到 Count(&total)的时候, 实际上这个时候的 DB 对象本身是含有 Value 了的, Value.ID 是根据你 where 条件的查询得到结果的最后一条的 ID. 没有再深入看 gorm 里面的代码, 我猜里面是有一个循环赋值的过程, 当你用 Count(&total)进行查询的时候, DB 对象已经被 Find(result)循环赋值完, 成为 Find(result)结果的最后一条, 所以会多出来一个 and 条件. 如果你试试把 arg.ID 换成[1,2,3,4,5], 那这个 where 条件应该会变成 and id = 5. 表述的可能不太清楚, 你可以自己试试 debug, 把断点打在 Count 方法的`return s.NewScope(s.Value).count(value).db `这一行就可以了~ |
9
Ansen OP @JimmyTinsley #8 非常感谢,我去验证了一下,就是你说的这个问题
如果我先 Find 再 Count 必定会多出一个 and id = arg.ID [-1] 的条件出来 我将代码改成下面这样,结果和 sql 语句就是正确的 err := db.Model(result).Where(id).Count(&total).Error err = db.Where(id).Find(result).Error |
10
JimmyTinsley 2019-09-05 09:52:24 +08:00
@Ansen #9 哈哈解决问题了就好
|
11
Ansen OP @JimmyTinsley #10
官方文档里面说可以像我之前那个用 http://gorm.io/docs/query.html#Count 感觉应该是 gorm 的 bug,我提了个 issues 看看官方杂说 https://github.com/jinzhu/gorm/issues/2647 |
12
JimmyTinsley 2019-09-05 10:28:21 +08:00
@Ansen #11 看文档里面确实是可以这样用, subscribe 了这个 issue 看看开发者怎么说
|