I’m using this function to get orders by status, the problem with this function is that the filtering happens after I get all my orders from redis is there a way to filter by value redis-side like in Postgres (a where statement for example) or does redis not support that?
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
}
2
Answers
The closest you could get since you are storing a serialized JSON array at a single key is to run a Lua script using
EVAL
that parses the JSON stored at the key, filters the entries based on thestatus
value, and then re-serializes and saves the results either at the same key or a different key. This would be faster in that it would be executed entirely on the Redis server, but it is also harder to debug / more error-prone.You can use
cjson.decode
to parse JSON andcjson.encode
to re-serialize it.Something like this:
I would use https://github.com/tidwall/gjson to query the marshalledStories