在 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