gorm的Scopes,DryRun 模式,子查询案例

如果以拼接sql字符串来做的话,可能相对容易些,以前用过laravel的orm,感觉写起来叶没有那么困难,而转化为gorm时,则感觉花了比较久,也可能是因为还不熟悉的原因。
此次用到Scopes,感觉有点类似闭包,用到了子查询,以及DryRun模式,应用的gorm的技巧较多,只是完成一个功能。具体看代码。

package main

import (
	"fmt"
	"gorm.io/gorm"
	"time"
)

var GDB *gorm.DB

type Ae struct {
	Id      int32     `json:"id"`
	AId     int32     `json:"a_id"`
	BeginAt time.Time `json:"begin_at"`
	EndAt   time.Time `json:"end_at"`
}
type A struct {
	Id      int32     `json:"id"`
	BeginAt time.Time `json:"begin_at"`
	EndAt   time.Time `json:"end_at"`
	Aes     []Ae      `json:"aes"`
}

func main() {
	GDB = getDB()
	GDB.AutoMigrate(A{}, Ae{})
	A1 := A{
		BeginAt: time.Date(2022, 7, 11, 0, 0, 0, 0, time.Local),
		EndAt:   time.Date(2022, 7, 18, 0, 0, 0, 0, time.Local),
		Aes: []Ae{
			{
				BeginAt: time.Date(2022, 7, 22, 0, 0, 0, 0, time.Local),
				EndAt:   time.Date(2022, 7, 23, 0, 0, 0, 0, time.Local),
			},
		},
	}
	// 创建记录
	GDB.Create(&A1)
	// 简单测试
	fmt.Println(count("2022-07-01", "2022-07-10"))
	fmt.Println(count("2022-07-17", "2022-07-19"))
	fmt.Println(count("2022-07-11", "2022-07-22"))
}

/**
count 作用是找出总数,条件是a的时间范围在该查询的时间范围内(dateBegin ~ dateEnd),或者关联的ae的时间范围在该时间范围内
sql:
select count(*) from a where
(
(date(end_at) >= ? and date(begin_at) <= ?)
or exists
(select id from ae where date(end_at) >= ? and date(begin_at) <= ? and ae.a_id=a.id)
)
*/
func count(dateBegin, dateEnd string) int64 {
	db := GDB.Model(&A{})
	if dateBegin != "" || dateEnd != "" {
		sub := GDB.Model(&Ae{}).Select("Id").Where("a_id = a.id")
		if dateBegin != "" {
			sub.Where("date(end_at) >= ?", dateBegin)
		}
		if dateEnd != "" {
			sub.Where("date(begin_at) <= ?", dateEnd)
		}
		dryRunDB := GDB.Session(&gorm.Session{DryRun: true})
		db.Where(db.Where(dryRunDB.Scopes(func(tx *gorm.DB) *gorm.DB {
			if dateBegin != "" || dateEnd != "" {
				if dateBegin != "" {
					tx.Where("date(end_at) >= ?", dateBegin)
				}
				if dateEnd != "" {
					tx.Where("date(begin_at) <= ?", dateEnd)
				}
				return tx
			}
			return tx
		})).Or(dryRunDB.Where("exists (?)", sub)))
	}
	var count int64
	db.Count(&count)
	return count
}
posted @   burndust  阅读(1433)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示