分享 golang 一种快捷自动实现查询条件构建的思路 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
8520ccc

分享 golang 一种快捷自动实现查询条件构建的思路

  •  1
     
  •   8520ccc 2023 年 3 月 7 日 1943 次点击
    这是一个创建于 1145 天前的主题,其中的信息可能已经有所发展或是发生改变。

    之前的方案

    我之前的方案就是给每个需要查询的字段加到请求的 struct 中,然后在请求时判断是否为空,不为空时则加入到查询条件

    type TransferFetchReq struct { g.Meta `path:"/transfer/fetch" method:"post" sm:"列表转账" tags:"转账"` types.PageReq UserID int64 `json:"user_id" dc:"用户 ID"` } //在控制器中加入 if req.UserID != 0 { u = u.Where("user_id = ?", req.UserID) } 

    但是这样的方案需要给每个条件写一份代码,太耗时间了

    新的方案

    把时间拿去写 struct 即可,如下:

    type TransferFetchFilter struct { ID int64 `json:"id"` CreatedAt []int64 `json:"created_at" cond:"between" dc:"创建时间"` UpdatedAt []int64 `json:"updated_at" cond:"between" dc:"更新时间"` FromID int64 `json:"from_id" dc:"转出用户 ID"` DestID int64 `json:"dest_id" dc:"转入用户 ID"` Code string `json:"code"` Type []uint `json:"type" cond:"in"` State []uint `json:"state" cond:"in"` } 

    如上,只需要写好这样的 struct ,即可完成所有字段的查询,可以通过 cond 指定查询方法 例如 LIKE/EQ/IN/NOTIN/between 等....

    当然,前提是必须把对应的数据类型写对(否则不会生效)

    例如查询方案为:IN 时 则数据类型必须是 []xxx

    默认为 EQ 即等于 则不能是 slice 默认查询字段取 json tag 当然还可以有一个更高优先级的 tag 例如 bind 这样可以同时对一个字段提供多种查询方法 这样就方便多了....................

    14 条回复    2023-03-12 10:27:21 +08:00
    lesismal
        1
    lesismal  
       2023 年 3 月 8 日
    ORM 没什么好的,试试我这个丫:
    https://github.com/lesismal/sqlw
    8520ccc
        2
    8520ccc  
    OP
       2023 年 3 月 8 日 via iPhone
    @lesismal 你这个太折磨人了

    我不手写 sql 的
    一是不太会写,二是怕有注入漏洞

    目前 ORM 用的挺爽
    lesismal
        3
    lesismal  
       2023 年 3 月 8 日
    之前在其他帖子也聊过,其实基础知识部分而言,学习 sql 本身并不比学习 orm 需要更多时间,而且逐渐积累起来,你对项目的掌控能力更强,尤其是性能相关,这是对于做大一些的项目的一些核心能力、涨工资或者说进阶的必备知识。一开始便依赖 orm ,并且不求深究,相当于自断了技术进阶的道路。
    当然,比如家里条件比较好、只是给自己定位 curd 中小项目,追求的是 work life balance and happiness ,那就无所谓了、orm 挺好
    8520ccc
        4
    8520ccc  
    OP
       2023 年 3 月 8 日 via iPhone
    @lesismal I don’t care 我不上班,都是自己做事情的
        5
    zmqiang  
       2023 年 3 月 8 日   1
    @lesismal 你这项目蛮有意思的,我来看一看
    thinkingbullet
        6
    thinkingbullet  
       2023 年 3 月 8 日
    gorm?另外我觉的 between 查询 应该写成 CreatedAt [2]int64, 限定是数组,必须有两个元素
    lesismal
        7
    lesismal  
       2023 年 3 月 8 日
    @8520ccc #4 那就无所谓了,自己用着舒服就是最好的
    @zmqiang 欢迎使用!
    8520ccc
        8
    8520ccc  
    OP
       2023 年 3 月 8 日 via iPhone
    @thinkingbullet 不限定,到时候自动判定入参个数截取即可
    8520ccc
        9
    8520ccc  
    OP
       2023 年 3 月 8 日 via iPhone
    @lesismal 嗯嗯,我目前是以开发效率为前提的

    性能暂时不考虑(因为前期根本不存在性能问题)

    真的出现性能问题,再优化也来得及
    ace12
        10
    ace12  
       2023 年 3 月 8 日
    8520ccc
        11
    8520ccc  
    OP
       2023 年 3 月 9 日 via iPhone
    @ace12 思路差不多,不过我没做 or 这些,因为我前端查询不需要 OR 这个
    thinkingbullet
        12
    thinkingbullet  
       2023 年 3 月 9 日
    @ace12 你这里有这样一句话 "当值为 0 值或空值或者 op tag 值为"-"会跳过" 那我必须要查为 0 值或为空值怎么办呢,比如 where status=0
    ace12
        13
    ace12  
       2023 年 3 月 10 日
    @thinkingbullet 之前还真没有考虑 null 的查询 现在加上啦

    ```go
    type UserWhere8 struct {
    DeletedAt bool `op:"null"` //为 true 时查询 IS NULL 为 false 时跳过条件
    Status *int
    CreatedAt *bool `op:"null"` //为 true 时查询 IS NULL ,为 false 时查询 IS NOT NULL
    }
    var status int
    var created bool
    u9 := UserWhere8{
    DeletedAt: true,
    Status: &status,
    CreatedAt: &created,
    }

    var user []User
    //SELECT * FROM `user` WHERE deleted_at IS NULL AND status = 0 AND created_at IS NOT NULL
    DB.Scopes(structquery.Where(u9)).Find(&user)
    ```
    thinkingbullet
        14
    thinkingbullet  
       2023 年 3 月 12 日
    @ace12 nice 果断 star
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     935 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 38ms UTC 19:13 PVG 03:13 LAX 12:13 JFK 15:13
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86