Golang Go语言中请教一下 Gorm 的 Count 问题

发布于 1周前 作者 nodeper 来自 Go语言

Golang Go语言中请教一下 Gorm 的 Count 问题

Count 方法这里怎么会多出一个 and 条件,导致结果不正确呢,我代码有问题么?

go 新手 求指点

代码片段

util 中部分定义:

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
}

}


更多关于Golang Go语言中请教一下 Gorm 的 Count 问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

13 回复

建议提问题的时候简明扼要一点,这里无关的东西太多了。
我的印象中 Find,和 Count 应该分开用吧,你这样想一下查两个值应该有点问题。
开一下 orm 的 log,测试两下不就出来了么。

更多关于Golang Go语言中请教一下 Gorm 的 Count 问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


验证了一下,这么用也是对的,gorm 拆分成两个 sql 语句了。
问题应该在与你的 db 对象,前面已经加了条件了。

红框里的应该是 Where(id)这一句导致的吧

并不行,分开使用一样不行,我是尝试过才来提问的,没有拿来主义

我看官方文档是可以这样用的

db 对象没有加条件,下面的代码片段可以看到,出了 midel 其它相关基本都贴出来了

把 SQL 打印一下,看看。

#6 图里面有,然后我再贴一下多出 and 的那条语句

sql<br><br>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))) <br>

#5 用 goland 帮你 debug 了一下
如果按照你的写法 db.Where(id).Find(result).Count(&amp;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<br>这一行就可以了~

#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

#9 哈哈解决问题了就好

#10
官方文档里面说可以像我之前那个用

http://gorm.io/docs/query.html#Count

感觉应该是 gorm 的 bug,我提了个 issues 看看官方杂说

https://github.com/jinzhu/gorm/issues/2647

#11 看文档里面确实是可以这样用, subscribe 了这个 issue 看看开发者怎么说

在Golang中使用Gorm进行数据库操作时,Count 方法是一个非常实用的功能,用于计算符合查询条件的记录数。下面是一些关于如何在Gorm中使用 Count 方法的要点:

  1. 基本用法Count 方法通常用于计算表中的记录数。例如,要计算 users 表中的总记录数,可以这样做:

    var count int64
    result := db.Model(&User{}).Count(&count).Error
    if result != nil {
        // 处理错误
    }
    fmt.Println("Total users:", count)
    
  2. 带条件的计数: 你也可以在 Count 方法中使用条件来限制计数范围。例如,要计算年龄大于30的用户数量,可以这样做:

    var count int64
    result := db.Model(&User{}).Where("age > ?", 30).Count(&count).Error
    if result != nil {
        // 处理错误
    }
    fmt.Println("Users older than 30:", count)
    
  3. 注意事项

    • 确保传递给 Count 的变量是 *int64 类型,因为 Gorm 会将计数结果存储在这个变量中。
    • 如果查询过程中出现错误,Count 方法会返回一个错误对象,记得进行错误处理。
    • Count 方法不会返回查询结果集,只会返回符合条件的记录数。

希望这些信息能帮助你更好地理解和使用Gorm中的 Count 方法。如果有其他问题或需要进一步的帮助,请随时提问。

回到顶部