优化mongo,封装count逻辑,处理objectId

This commit is contained in:
2026-01-06 17:01:10 +08:00
parent a43da6e06e
commit 213ad95791
8 changed files with 123 additions and 91 deletions

View File

@@ -4,10 +4,12 @@ import (
"context"
"errors"
"fmt"
"reflect"
"strings"
"sync"
"time"
"gitee.com/red-future---jilin-g/common/beans"
"gitee.com/red-future---jilin-g/common/log/model/dto"
"github.com/gogf/gf/v2/container/gvar"
@@ -219,56 +221,11 @@ func close() {
isConnected = false
glog.Info(context.Background(), "MongoDB连接已关闭")
}
func listOptionsToMap(ctx context.Context, opts ...options.Lister[options.FindOptions]) (m map[string]interface{}) {
// 输出opts参数中的值
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
}
const PageSize = 20
// 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 {
return
}
@@ -277,34 +234,79 @@ func (m *MongoDB) Find(ctx context.Context, filter bson.M, result interface{}, c
return
}
filter["isDeleted"] = false
filterMap := utils.OrderMap(filter)
optsMap := listOptionsToMap(ctx, opts...)
redisKey := fmt.Sprintf(redis.List, user.TenantId, collection, gconv.String(filterMap), gconv.String(optsMap))
filterKey := fmt.Sprintf("%+v", filter)
optionsKey := fmt.Sprintf("%+v%+v", page, orderBy)
redisKey := fmt.Sprintf(redis.List, user.TenantId, collection, filterKey, optionsKey)
resultValue := reflect.ValueOf(result)
resultValue = resultValue.Elem()
listField := resultValue.FieldByName("List")
if m.Cache {
var resultStr *gvar.Var
resultStr, err = redis.RedisClient.Get(ctx, redisKey)
if err != nil {
return
}
if !g.IsEmpty(resultStr) {
err = gconv.Scan(resultStr, result)
if err != nil {
return err
}
if !resultStr.IsEmpty() {
resultStr.Structs(listField.Addr().Interface())
return
}
}
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 {
return
}
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
}
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 {
return err
}
@@ -326,8 +328,8 @@ func (m *MongoDB) FindOne(ctx context.Context, filter bson.M, result interface{}
return
}
filter["isDeleted"] = false
filterMap := utils.OrderMap(filter)
redisKey := fmt.Sprintf(redis.One, user.TenantId, collection, gconv.String(filterMap))
filterKey := fmt.Sprintf("%+v", filter)
redisKey := fmt.Sprintf(redis.One, user.TenantId, collection, filterKey)
if m.Cache {
var resultStr *gvar.Var
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
delete(filter, "tenantId")
filterMap := utils.OrderMap(filter)
oneKey := fmt.Sprintf(redis.One, tenantId, collection, gconv.String(filterMap))
filterKey := fmt.Sprintf("%+v", filter)
oneKey := fmt.Sprintf(redis.One, tenantId, collection, filterKey)
_, err = redis.RedisClient.Del(ctx, oneKey)
if err != nil {
return
@@ -404,7 +406,7 @@ func (m *MongoDB) Delete(ctx context.Context, filter bson.M, collection string,
}
filter["tenantId"] = user.TenantId
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
}
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
update = bson.M{"$set": setDoc}
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
}
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)
} else {
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
}
}
@@ -652,8 +654,9 @@ func (m *MongoDB) Count(ctx context.Context, filter bson.M, collection string) (
return
}
filter["isDeleted"] = false
filterMap := utils.OrderMap(filter)
redisKey := fmt.Sprintf(redis.Count, user.TenantId, collection, gconv.String(filterMap))
delete(filter, "tenantId")
filterKey := fmt.Sprintf("%+v", filter)
redisKey := fmt.Sprintf(redis.Count, user.TenantId, collection, filterKey)
if m.Cache {
var resultStr *gvar.Var
resultStr, err = redis.RedisClient.Get(ctx, redisKey)