mongodb基础操作方法增加redis缓存策略
This commit is contained in:
7
consts/redis_key.go
Normal file
7
consts/redis_key.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package consts
|
||||||
|
|
||||||
|
const CleanList = "list:tenantId-%v:collection-%s:*"
|
||||||
|
const CleanCount = "count:tenantId-%v:collection-%s:*"
|
||||||
|
const List = "list:tenantId-%v:collection-%s:filter:%s:options:%s"
|
||||||
|
const Count = "count:tenantId-%v:collection-%s:filter:%s"
|
||||||
|
const One = "one:tenantId-%v:collection-%s:filter:%s:*"
|
||||||
135
mongo/mongo.go
135
mongo/mongo.go
@@ -2,9 +2,13 @@ package mongo
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gitee.com/red-future---jilin-g/common/consts"
|
||||||
|
"gitee.com/red-future---jilin-g/common/redis"
|
||||||
"gitee.com/red-future---jilin-g/common/utils"
|
"gitee.com/red-future---jilin-g/common/utils"
|
||||||
"github.com/gogf/gf/v2/errors/gerror"
|
"github.com/gogf/gf/v2/errors/gerror"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
@@ -36,23 +40,88 @@ func init() {
|
|||||||
}
|
}
|
||||||
db = client.Database(dbName)
|
db = client.Database(dbName)
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
// Find 查询多条记录
|
// Find 查询多条记录
|
||||||
func Find(ctx context.Context, filter bson.M, result interface{}, collection string, opts ...options.Lister[options.FindOptions]) (err error) {
|
func Find(ctx context.Context, filter bson.M, result interface{}, collection string, opts ...options.Lister[options.FindOptions]) (err error) {
|
||||||
if err = utils.ValidStructPtr(result); err != nil {
|
if err = utils.ValidStructPtr(result); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
filter["isDeleted"] = false
|
|
||||||
user, err := utils.GetUserInfo(ctx)
|
user, err := utils.GetUserInfo(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
filter["isDeleted"] = false
|
||||||
filter["tenantId"] = user.TenantId
|
filter["tenantId"] = user.TenantId
|
||||||
|
filterMap := utils.OrderMap(filter)
|
||||||
|
optsMap := listOptionsToMap(ctx, opts...)
|
||||||
|
redisKey := fmt.Sprintf(consts.List, user.TenantId, collection, gconv.String(filterMap), gconv.String(optsMap))
|
||||||
|
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
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
cur, err := db.Collection(collection).Find(ctx, filter, opts...)
|
cur, err := db.Collection(collection).Find(ctx, filter, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = cur.All(ctx, result)
|
err = cur.All(ctx, result)
|
||||||
|
err = redis.RedisClient.SetEX(ctx, redisKey, result, int64(time.Hour))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,17 +134,35 @@ func FindOne(ctx context.Context, filter bson.M, result interface{}, collection
|
|||||||
if err = utils.ValidStructPtr(result); err != nil {
|
if err = utils.ValidStructPtr(result); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
filter["isDeleted"] = false
|
|
||||||
user, err := utils.GetUserInfo(ctx)
|
user, err := utils.GetUserInfo(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
filter["isDeleted"] = false
|
||||||
filter["tenantId"] = user.TenantId
|
filter["tenantId"] = user.TenantId
|
||||||
|
filterMap := utils.OrderMap(filter)
|
||||||
|
optsMap := oneOptionsToMap(ctx, opts...)
|
||||||
|
redisKey := fmt.Sprintf(consts.One, user.TenantId, collection, gconv.String(filterMap), gconv.String(optsMap))
|
||||||
|
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
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
cur := db.Collection(collection).FindOne(ctx, filter, opts...)
|
cur := db.Collection(collection).FindOne(ctx, filter, opts...)
|
||||||
err = cur.Decode(result)
|
err = cur.Decode(result)
|
||||||
if err == mongo.ErrNoDocuments {
|
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
|
err = redis.RedisClient.SetEX(ctx, redisKey, result, int64(time.Hour))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,6 +182,14 @@ func Delete(ctx context.Context, filter bson.M, collection string, opts ...optio
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
count = r.DeletedCount
|
count = r.DeletedCount
|
||||||
|
_, err = redis.RedisClient.Del(ctx, fmt.Sprintf(consts.CleanList, user.TenantId, collection))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = redis.RedisClient.Del(ctx, fmt.Sprintf(consts.CleanCount, user.TenantId, collection))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +213,14 @@ func Update(ctx context.Context, filter bson.M, update bson.M, collection string
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
_, err = redis.RedisClient.Del(ctx, fmt.Sprintf(consts.CleanList, user.TenantId, collection))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = redis.RedisClient.Del(ctx, fmt.Sprintf(consts.CleanCount, user.TenantId, collection))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,13 +247,39 @@ func Insert(ctx context.Context, documents []interface{}, collection string, opt
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
ids = r.InsertedIDs
|
ids = r.InsertedIDs
|
||||||
|
_, err = redis.RedisClient.Del(ctx, fmt.Sprintf(consts.CleanList, user.TenantId, collection))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = redis.RedisClient.Del(ctx, fmt.Sprintf(consts.CleanCount, user.TenantId, collection))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count 查询总数
|
// Count 查询总数
|
||||||
func Count(ctx context.Context, filter bson.M, collection string) (count int64, err error) {
|
func Count(ctx context.Context, filter bson.M, collection string) (count int64, err error) {
|
||||||
|
user, err := utils.GetUserInfo(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
filter["isDeleted"] = false
|
filter["isDeleted"] = false
|
||||||
|
filterMap := utils.OrderMap(filter)
|
||||||
|
redisKey := fmt.Sprintf(consts.Count, user.TenantId, collection, gconv.String(filterMap))
|
||||||
|
resultStr, err := redis.RedisClient.Get(ctx, redisKey)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !g.IsEmpty(resultStr) {
|
||||||
|
count = gconv.Int64(resultStr)
|
||||||
|
return
|
||||||
|
}
|
||||||
// 调用驱动的 CountDocuments,在数据库端执行的
|
// 调用驱动的 CountDocuments,在数据库端执行的
|
||||||
count, err = db.Collection(collection).CountDocuments(ctx, filter)
|
count, err = db.Collection(collection).CountDocuments(ctx, filter)
|
||||||
|
err = redis.RedisClient.SetEX(ctx, redisKey, count, int64(time.Hour))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gitee.com/red-future---jilin-g/common/do"
|
"gitee.com/red-future---jilin-g/common/do"
|
||||||
@@ -92,3 +93,22 @@ func GetUserInfo(ctx context.Context) (user do.User, err error) {
|
|||||||
user.TenantId = dataMap["tenantId"]
|
user.TenantId = dataMap["tenantId"]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func OrderMap(m map[string]interface{}) map[string]interface{} {
|
||||||
|
// 提取所有key
|
||||||
|
keys := make([]string, 0, len(m))
|
||||||
|
for k := range m {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用标准排序算法对key进行排序
|
||||||
|
// 使用strings.Sort确保排序结果永远一致
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
// 创建有序map
|
||||||
|
orderedMap := make(map[string]interface{}, len(m))
|
||||||
|
for _, k := range keys {
|
||||||
|
orderedMap[k] = m[k]
|
||||||
|
}
|
||||||
|
|
||||||
|
return orderedMap
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user