在 Redis 中按值过滤(使用 go 和 redis-go)
Filtering by value in Redis (using go and redis-go)
我正在使用此功能按状态获取订单,此功能的问题是在我从 redis 获取所有订单后进行过滤是否有一种方法可以像 Postgres 一样按值 redis 端进行过滤(例如 where 语句)或者 redis 不支持吗?
func (r *queryResolver) OrdersByStatus(ctx context.Context, status string) ([]*models.Order, error) {
defer utils.Elapsed("redis query => orders")()
myCtx := ctx.Value(constants.KMyContext).(types.MyCtx)
sessionData, sessionErr := session.GetSessionData(myCtx.ResponseWriter, myCtx.Request, constants.KCurrentUser)
if sessionErr != nil {
return nil, sessionErr
}
marshalledStories, err := cache.RedisClient.Get(ctx, constants.KOrders+sessionData.UUID).Result()
if err != nil {
log.Println("redis get err", err)
return nil, errors.New(constants.InternalServerError)
}
var orders []*models.Order
unmarshallErr := json.Unmarshal([]byte(marshalledStories), &orders)
if unmarshallErr != nil {
log.Println("redis unmarshallErr", unmarshallErr)
return nil, errors.New(constants.InternalServerError)
}
var filtered []*models.Order
for _, u := range orders {
if u.Status == status {
filtered = append(filtered, u)
}
}
return filtered, nil
}
自从您将序列化的 JSON 数组存储在单个键中以来,您可以获得的最接近结果是 运行 一个 Lua 使用 EVAL
解析 JSON 存储在键中,根据 status
值过滤条目,然后重新序列化并保存在相同键或不同键中的结果。这会更快,因为它将完全在 Redis 服务器上执行,但也更难调试/更容易出错。
您可以使用 cjson.decode
解析 JSON 并使用 cjson.encode
重新序列化它。
像这样:
local myKey = KEYS[1]
local status = ARGV[1]
local raw = redis.call("GET", myKey)
local orders = cjson.decode(raw)
local filteredOrders = {}
local index = 1
for order, _ in ipairs(orders) do
if order["status"] == status then
filteredOrders[index] = order
index = index + 1
end
end
local resultRaw = cjson.encode(filteredOrders)
redis.call("SET", myKey, resultRaw)
我会使用 https://github.com/tidwall/gjson 来查询 marshalledStories
我正在使用此功能按状态获取订单,此功能的问题是在我从 redis 获取所有订单后进行过滤是否有一种方法可以像 Postgres 一样按值 redis 端进行过滤(例如 where 语句)或者 redis 不支持吗?
func (r *queryResolver) OrdersByStatus(ctx context.Context, status string) ([]*models.Order, error) {
defer utils.Elapsed("redis query => orders")()
myCtx := ctx.Value(constants.KMyContext).(types.MyCtx)
sessionData, sessionErr := session.GetSessionData(myCtx.ResponseWriter, myCtx.Request, constants.KCurrentUser)
if sessionErr != nil {
return nil, sessionErr
}
marshalledStories, err := cache.RedisClient.Get(ctx, constants.KOrders+sessionData.UUID).Result()
if err != nil {
log.Println("redis get err", err)
return nil, errors.New(constants.InternalServerError)
}
var orders []*models.Order
unmarshallErr := json.Unmarshal([]byte(marshalledStories), &orders)
if unmarshallErr != nil {
log.Println("redis unmarshallErr", unmarshallErr)
return nil, errors.New(constants.InternalServerError)
}
var filtered []*models.Order
for _, u := range orders {
if u.Status == status {
filtered = append(filtered, u)
}
}
return filtered, nil
}
自从您将序列化的 JSON 数组存储在单个键中以来,您可以获得的最接近结果是 运行 一个 Lua 使用 EVAL
解析 JSON 存储在键中,根据 status
值过滤条目,然后重新序列化并保存在相同键或不同键中的结果。这会更快,因为它将完全在 Redis 服务器上执行,但也更难调试/更容易出错。
您可以使用 cjson.decode
解析 JSON 并使用 cjson.encode
重新序列化它。
像这样:
local myKey = KEYS[1]
local status = ARGV[1]
local raw = redis.call("GET", myKey)
local orders = cjson.decode(raw)
local filteredOrders = {}
local index = 1
for order, _ in ipairs(orders) do
if order["status"] == status then
filteredOrders[index] = order
index = index + 1
end
end
local resultRaw = cjson.encode(filteredOrders)
redis.call("SET", myKey, resultRaw)
我会使用 https://github.com/tidwall/gjson 来查询 marshalledStories