优化mongo,封装count逻辑,处理objectId
This commit is contained in:
@@ -10,11 +10,22 @@ type ResponseEmpty struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Page struct {
|
type Page struct {
|
||||||
PageNum int `p:"pageNum"` //当前页码
|
PageNum int64 `p:"pageNum"` //当前页码
|
||||||
PageSize int `p:"pageSize"` //每页数
|
PageSize int64 `p:"pageSize"` //每页数
|
||||||
Total int //总页数
|
Total int64 //总页数
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OrderEnum string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Asc OrderEnum = "asc" // 正序
|
||||||
|
Desc OrderEnum = "desc" // 倒序
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrderBy struct {
|
||||||
|
Field string `p:"field"` //排序字段
|
||||||
|
Order OrderEnum `p:"order"` //排序方式
|
||||||
|
}
|
||||||
type MongoBaseDO struct {
|
type MongoBaseDO struct {
|
||||||
Id bson.ObjectID `bson:"_id,omitempty" json:"id"` // MongoDB 默认 ID
|
Id bson.ObjectID `bson:"_id,omitempty" json:"id"` // MongoDB 默认 ID
|
||||||
Creator interface{} `bson:"creator,omitempty" json:"creator"`
|
Creator interface{} `bson:"creator,omitempty" json:"creator"`
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ import (
|
|||||||
"github.com/gogf/gf/v2/util/gconv"
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
const PageSize = 20
|
|
||||||
|
|
||||||
var Httpserver = g.Server()
|
var Httpserver = g.Server()
|
||||||
var Httpclient = g.Client()
|
var Httpclient = g.Client()
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"gitee.com/red-future---jilin-g/common/log/model/dto"
|
"gitee.com/red-future---jilin-g/common/log/model/dto"
|
||||||
"gitee.com/red-future---jilin-g/common/log/service"
|
"gitee.com/red-future---jilin-g/common/log/service"
|
||||||
@@ -32,13 +31,7 @@ func (c *operationLog) GetByID(ctx context.Context, req *dto.GetLogReq) (res *dt
|
|||||||
// @Summary 查询操作日志列表
|
// @Summary 查询操作日志列表
|
||||||
// @Description 根据多个条件查询操作日志列表
|
// @Description 根据多个条件查询操作日志列表
|
||||||
func (c *operationLog) List(ctx context.Context, req *dto.ListLogsReq) (res *dto.ListLogsResp, err error) {
|
func (c *operationLog) List(ctx context.Context, req *dto.ListLogsReq) (res *dto.ListLogsResp, err error) {
|
||||||
// 处理排序字段
|
logs, total, err := service.OperationLog.List(ctx, req)
|
||||||
var sortFields []string
|
|
||||||
if req.SortFields != "" {
|
|
||||||
sortFields = strings.Split(req.SortFields, ",")
|
|
||||||
}
|
|
||||||
|
|
||||||
logs, total, err := service.OperationLog.List(ctx, req, sortFields...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ func (d *log) List(ctx context.Context, filter *dto.ListLogsReq, sortFields ...s
|
|||||||
}
|
}
|
||||||
|
|
||||||
var logs []*entity.OperationLog
|
var logs []*entity.OperationLog
|
||||||
err = mongo.DB().Find(ctx, bsonFilter, &logs, consts.OperationLogCollection, findOptions...)
|
err = mongo.DB().Find(ctx, bsonFilter, &logs, consts.OperationLogCollection, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ type OperationLogInfo struct {
|
|||||||
type ListLogsReq struct {
|
type ListLogsReq struct {
|
||||||
g.Meta `path:"/listLogs" method:"get" tags:"操作日志" summary:"查询操作日志列表" dc:"根据多个条件查询操作日志列表"`
|
g.Meta `path:"/listLogs" method:"get" tags:"操作日志" summary:"查询操作日志列表" dc:"根据多个条件查询操作日志列表"`
|
||||||
beans.Page
|
beans.Page
|
||||||
ServiceName string `json:"service_name" dc:"服务名(可选)"`
|
ServiceName string `json:"service_name" dc:"服务名(可选)"`
|
||||||
Collection string `json:"collection" dc:"数据所在集合名称(可选)"`
|
Collection string `json:"collection" dc:"数据所在集合名称(可选)"`
|
||||||
CollectionID string `json:"collection_id" dc:"数据ID(可选)"`
|
CollectionID string `json:"collection_id" dc:"数据ID(可选)"`
|
||||||
Operation string `json:"operation" dc:"操作类型(可选)"`
|
Operation string `json:"operation" dc:"操作类型(可选)"`
|
||||||
StartTime string `json:"start_time" dc:"开始时间(可选)"`
|
StartTime string `json:"start_time" dc:"开始时间(可选)"`
|
||||||
EndTime string `json:"end_time" dc:"结束时间(可选)"`
|
EndTime string `json:"end_time" dc:"结束时间(可选)"`
|
||||||
SortFields string `json:"sort_fields" dc:"排序字段,多个用逗号分隔,如:-createdAt"`
|
OrderBy []beans.OrderBy `json:"orderBy" dc:"排序字段"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListLogsResp 查询操作日志列表响应
|
// ListLogsResp 查询操作日志列表响应
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ func (s *operationLog) GetByID(ctx context.Context, id string) (*dto.OperationLo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List 查询操作日志列表
|
// List 查询操作日志列表
|
||||||
func (s *operationLog) List(ctx context.Context, filter *dto.ListLogsReq, sortFields ...string) ([]dto.OperationLogInfo, int64, error) {
|
func (s *operationLog) List(ctx context.Context, req *dto.ListLogsReq) ([]dto.OperationLogInfo, int64, error) {
|
||||||
logs, total, err := dao.Log.List(ctx, filter, sortFields...)
|
logs, total, err := dao.Log.List(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|||||||
139
mongo/mongo.go
139
mongo/mongo.go
@@ -4,10 +4,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gitee.com/red-future---jilin-g/common/beans"
|
||||||
"gitee.com/red-future---jilin-g/common/log/model/dto"
|
"gitee.com/red-future---jilin-g/common/log/model/dto"
|
||||||
"github.com/gogf/gf/v2/container/gvar"
|
"github.com/gogf/gf/v2/container/gvar"
|
||||||
|
|
||||||
@@ -219,56 +221,11 @@ func close() {
|
|||||||
isConnected = false
|
isConnected = false
|
||||||
glog.Info(context.Background(), "MongoDB连接已关闭")
|
glog.Info(context.Background(), "MongoDB连接已关闭")
|
||||||
}
|
}
|
||||||
func listOptionsToMap(ctx context.Context, opts ...options.Lister[options.FindOptions]) (m map[string]interface{}) {
|
|
||||||
// 输出opts参数中的值
|
const PageSize = 20
|
||||||
m = make(map[string]interface{})
|
|
||||||
for _, opt := range opts {
|
|
||||||
var findOpts options.FindOptions
|
|
||||||
optFuncs := opt.List()
|
|
||||||
for _, fn := range optFuncs {
|
|
||||||
fn(&findOpts)
|
|
||||||
}
|
|
||||||
if findOpts.Limit != nil {
|
|
||||||
m["limit"] = *findOpts.Limit
|
|
||||||
}
|
|
||||||
if findOpts.Skip != nil {
|
|
||||||
m["skip"] = *findOpts.Skip
|
|
||||||
}
|
|
||||||
if findOpts.Sort != nil {
|
|
||||||
m["sort"] = findOpts.Sort
|
|
||||||
}
|
|
||||||
if findOpts.Projection != nil {
|
|
||||||
m["projection"] = findOpts.Projection
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m = utils.OrderMap(m)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func oneOptionsToMap(ctx context.Context, opts ...options.Lister[options.FindOneOptions]) (m map[string]interface{}) {
|
|
||||||
// 输出opts参数中的值
|
|
||||||
m = make(map[string]interface{})
|
|
||||||
for _, opt := range opts {
|
|
||||||
var findOpts options.FindOneOptions
|
|
||||||
optFuncs := opt.List()
|
|
||||||
for _, fn := range optFuncs {
|
|
||||||
fn(&findOpts)
|
|
||||||
}
|
|
||||||
if findOpts.Skip != nil {
|
|
||||||
m["skip"] = *findOpts.Skip
|
|
||||||
}
|
|
||||||
if findOpts.Sort != nil {
|
|
||||||
m["sort"] = findOpts.Sort
|
|
||||||
}
|
|
||||||
if findOpts.Projection != nil {
|
|
||||||
m["projection"] = findOpts.Projection
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m = utils.OrderMap(m)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find 查询多条记录
|
// Find 查询多条记录
|
||||||
func (m *MongoDB) Find(ctx context.Context, filter bson.M, result interface{}, collection string, opts ...options.Lister[options.FindOptions]) (err error) {
|
func (m *MongoDB) Find(ctx context.Context, filter bson.M, result interface{}, collection string, page *beans.Page, orderBy []beans.OrderBy) (err error) {
|
||||||
if err = utils.ValidStructPtr(result); err != nil {
|
if err = utils.ValidStructPtr(result); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -277,34 +234,79 @@ func (m *MongoDB) Find(ctx context.Context, filter bson.M, result interface{}, c
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
filter["isDeleted"] = false
|
filter["isDeleted"] = false
|
||||||
filterMap := utils.OrderMap(filter)
|
filterKey := fmt.Sprintf("%+v", filter)
|
||||||
optsMap := listOptionsToMap(ctx, opts...)
|
optionsKey := fmt.Sprintf("%+v%+v", page, orderBy)
|
||||||
redisKey := fmt.Sprintf(redis.List, user.TenantId, collection, gconv.String(filterMap), gconv.String(optsMap))
|
redisKey := fmt.Sprintf(redis.List, user.TenantId, collection, filterKey, optionsKey)
|
||||||
|
resultValue := reflect.ValueOf(result)
|
||||||
|
resultValue = resultValue.Elem()
|
||||||
|
listField := resultValue.FieldByName("List")
|
||||||
if m.Cache {
|
if m.Cache {
|
||||||
var resultStr *gvar.Var
|
var resultStr *gvar.Var
|
||||||
resultStr, err = redis.RedisClient.Get(ctx, redisKey)
|
resultStr, err = redis.RedisClient.Get(ctx, redisKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !g.IsEmpty(resultStr) {
|
if !resultStr.IsEmpty() {
|
||||||
err = gconv.Scan(resultStr, result)
|
resultStr.Structs(listField.Addr().Interface())
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
filter["tenantId"] = user.TenantId
|
filter["tenantId"] = user.TenantId
|
||||||
cur, err := db.Collection(collection).Find(ctx, filter, opts...)
|
|
||||||
|
// 分页参数处理
|
||||||
|
limit := int64(PageSize)
|
||||||
|
skip := int64(0)
|
||||||
|
if page != nil {
|
||||||
|
limit = page.PageSize
|
||||||
|
skip = (page.PageNum - 1) * limit
|
||||||
|
if skip <= 0 {
|
||||||
|
skip = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total, err := m.Count(ctx, filter, collection)
|
||||||
|
if err != nil || total == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
utils.SetValue(ctx, result, "Total", total)
|
||||||
|
opt := options.Find().SetSkip(skip)
|
||||||
|
if limit != -1 {
|
||||||
|
opt.SetLimit(limit)
|
||||||
|
}
|
||||||
|
if orderBy == nil {
|
||||||
|
opt.SetSort(bson.M{"createdAt": -1})
|
||||||
|
} else {
|
||||||
|
orderBson := bson.M{}
|
||||||
|
for _, v := range orderBy {
|
||||||
|
if v.Order == beans.Asc {
|
||||||
|
orderBson[v.Field] = 1
|
||||||
|
} else {
|
||||||
|
orderBson[v.Field] = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opt.SetSort(orderBson)
|
||||||
|
}
|
||||||
|
|
||||||
|
cur, err := db.Collection(collection).Find(ctx, filter, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer cur.Close(ctx)
|
defer cur.Close(ctx)
|
||||||
if err = cur.All(ctx, result); err != nil {
|
|
||||||
|
// 先解码到[]bson.M,再转换到目标类型,处理datetime到string的转换
|
||||||
|
var docs []bson.M
|
||||||
|
if err = cur.All(ctx, &docs); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, v := range docs {
|
||||||
|
v["id"] = v["_id"].(bson.ObjectID).Hex()
|
||||||
|
delete(v, "_id")
|
||||||
|
}
|
||||||
|
// 使用gconv转换,处理类型转换
|
||||||
|
if err = gconv.Structs(docs, listField.Addr().Interface()); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if m.Cache {
|
if m.Cache {
|
||||||
err = redis.RedisClient.SetEX(ctx, redisKey, result, int64(time.Hour))
|
err = redis.RedisClient.SetEX(ctx, redisKey, docs, int64(time.Hour))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -326,8 +328,8 @@ func (m *MongoDB) FindOne(ctx context.Context, filter bson.M, result interface{}
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
filter["isDeleted"] = false
|
filter["isDeleted"] = false
|
||||||
filterMap := utils.OrderMap(filter)
|
filterKey := fmt.Sprintf("%+v", filter)
|
||||||
redisKey := fmt.Sprintf(redis.One, user.TenantId, collection, gconv.String(filterMap))
|
redisKey := fmt.Sprintf(redis.One, user.TenantId, collection, filterKey)
|
||||||
if m.Cache {
|
if m.Cache {
|
||||||
var resultStr *gvar.Var
|
var resultStr *gvar.Var
|
||||||
resultStr, err = redis.RedisClient.Get(ctx, redisKey)
|
resultStr, err = redis.RedisClient.Get(ctx, redisKey)
|
||||||
@@ -383,8 +385,8 @@ func (m *MongoDB) CleanRedis(ctx context.Context, filter bson.M, tenantId interf
|
|||||||
}
|
}
|
||||||
filter["isDeleted"] = false
|
filter["isDeleted"] = false
|
||||||
delete(filter, "tenantId")
|
delete(filter, "tenantId")
|
||||||
filterMap := utils.OrderMap(filter)
|
filterKey := fmt.Sprintf("%+v", filter)
|
||||||
oneKey := fmt.Sprintf(redis.One, tenantId, collection, gconv.String(filterMap))
|
oneKey := fmt.Sprintf(redis.One, tenantId, collection, filterKey)
|
||||||
_, err = redis.RedisClient.Del(ctx, oneKey)
|
_, err = redis.RedisClient.Del(ctx, oneKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -404,7 +406,7 @@ func (m *MongoDB) Delete(ctx context.Context, filter bson.M, collection string,
|
|||||||
}
|
}
|
||||||
filter["tenantId"] = user.TenantId
|
filter["tenantId"] = user.TenantId
|
||||||
var rows []interface{}
|
var rows []interface{}
|
||||||
if err = m.Find(ctx, filter, &rows, collection); err != nil {
|
if err = m.Find(ctx, filter, &rows, collection, nil, nil); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r, err := db.Collection(collection).DeleteMany(ctx, filter, opts...)
|
r, err := db.Collection(collection).DeleteMany(ctx, filter, opts...)
|
||||||
@@ -446,7 +448,7 @@ func (m *MongoDB) Update(ctx context.Context, filter bson.M, update bson.M, coll
|
|||||||
setDoc["updatedAt"] = gtime.Now().Time
|
setDoc["updatedAt"] = gtime.Now().Time
|
||||||
update = bson.M{"$set": setDoc}
|
update = bson.M{"$set": setDoc}
|
||||||
var rows []interface{}
|
var rows []interface{}
|
||||||
if err = m.Find(ctx, filter, &rows, collection); err != nil {
|
if err = m.Find(ctx, filter, &rows, collection, nil, nil); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
result, err = db.Collection(collection).UpdateMany(ctx, filter, update, opts...)
|
result, err = db.Collection(collection).UpdateMany(ctx, filter, update, opts...)
|
||||||
@@ -631,7 +633,7 @@ func (m *MongoDB) Insert(ctx context.Context, documents []interface{}, collectio
|
|||||||
rows = append(rows, doc)
|
rows = append(rows, doc)
|
||||||
} else {
|
} else {
|
||||||
filter := bson.M{"_id": bson.M{"$in": ids}}
|
filter := bson.M{"_id": bson.M{"$in": ids}}
|
||||||
if err = m.Find(ctx, filter, &rows, collection); err != nil {
|
if err = m.Find(ctx, filter, &rows, collection, nil, nil); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -652,8 +654,9 @@ func (m *MongoDB) Count(ctx context.Context, filter bson.M, collection string) (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
filter["isDeleted"] = false
|
filter["isDeleted"] = false
|
||||||
filterMap := utils.OrderMap(filter)
|
delete(filter, "tenantId")
|
||||||
redisKey := fmt.Sprintf(redis.Count, user.TenantId, collection, gconv.String(filterMap))
|
filterKey := fmt.Sprintf("%+v", filter)
|
||||||
|
redisKey := fmt.Sprintf(redis.Count, user.TenantId, collection, filterKey)
|
||||||
if m.Cache {
|
if m.Cache {
|
||||||
var resultStr *gvar.Var
|
var resultStr *gvar.Var
|
||||||
resultStr, err = redis.RedisClient.Get(ctx, redisKey)
|
resultStr, err = redis.RedisClient.Get(ctx, redisKey)
|
||||||
|
|||||||
@@ -107,7 +107,34 @@ func GetUserInfo(ctx context.Context) (user beans.User, err error) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func SetValue(ctx context.Context, result any, key string, value any) {
|
||||||
|
// 检查context是否已取消
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
// 使用反射设置result的Total属性
|
||||||
|
resultValue := reflect.ValueOf(result)
|
||||||
|
if resultValue.Kind() == reflect.Ptr {
|
||||||
|
resultValue = resultValue.Elem()
|
||||||
|
totalField := resultValue.FieldByName(key)
|
||||||
|
if totalField.IsValid() && totalField.CanSet() {
|
||||||
|
totalField.Set(reflect.ValueOf(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func Struts(ctx context.Context, pointer any, mapping ...map[string]string) {
|
||||||
|
// 检查context是否已取消
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
func OrderMap(m map[string]interface{}) map[string]interface{} {
|
func OrderMap(m map[string]interface{}) map[string]interface{} {
|
||||||
// 提取所有key
|
// 提取所有key
|
||||||
keys := make([]string, 0, len(m))
|
keys := make([]string, 0, len(m))
|
||||||
|
|||||||
Reference in New Issue
Block a user