sql >> Base de Datos >  >> NoSQL >> Redis

Actualización de la lista Redis de la pila de servicios

Listas a evitar:

Desafortunadamente, las listas de Redis no son realmente una buena opción. en esta situación. Tuve el mismo problema cuando comencé a usar Redis, parecen ser la opción obvia;). Las listas de Redis son útiles si las usa como un conjunto de solo lectura, o si solo desea hacer estallar y empujar, pero no para modificar un elemento en el medio de la lista.

Puede "actualizar" elementos en una lista de Redis si conoce el índice del elemento, pero requiere eliminar y volver a insertar , y debe ser por índice, cuya determinación es terriblemente ineficiente. Lo hace iterando la colección, porque no hay una forma nativa de hacerlo, y no es una buena idea. Este es un fragmento del IndexOf método de RedisClientList<T> .

public int IndexOf(T item)
{
    //TODO: replace with native implementation when exists
    var i = 0;
    foreach (var existingItem in this)
    {
        if (Equals(existingItem, item)) return i;
        i++;
    }
    return -1;
}

Entonces, para completar su código, sería:

public void UpdatePizza(Pizza pizza)
{
    using (var redisClient = new RedisClient(Host, Port))
    {
        IRedisTypedClient<Pizza> redis = redisClient.As<Pizza>();
        IRedisList<Pizza> pizzas = redis.Lists["pizzas:live"];
        var toUpdate = pizzas.First(x => x.Id == pizza.Id);
        toUpdate.State = pizza.State;

        // Update by removing & inserting (don't do it!)
        var index = pizzas.IndexOf(toUpdate);
        pizzas.Remove(index);
        pizzas.Insert(index, toUpdate);
    }                   
}

Pero esta no es una buena manera de manejarlo como he dicho. Recuperará la lista de los otros objetos de pizza y luego iterará sobre ellos hasta que coincida con el índice. ¡Y dos operaciones para actualizar! :( Es mejor evitar las listas en esta situación.

Solución:

Mientras intenta acceder a la pizza por su ID, puede crear una clave de pizza única para cada objeto, esto le permitirá acceder a la pizza directamente. Así que podríamos usar:

pizzas:live:{Id}

Ejemplos:

Crear una pizza

using (var redisClient = new RedisClient())
{
    IRedisTypedClient<Pizza> redis = redisClient.As<Pizza>();
    var pizzaKey = string.Format("pizzas:live:{0}", 123);
    var pizza = new Pizza { Id = 123, Type = "Mushroom", State = "Cooking" };
    redis.SetEntry(pizzaKey, pizza);
}

Obtener una pizza por identificación

using (var redisClient = new RedisClient())
{
    IRedisTypedClient<Pizza> redis = redisClient.As<Pizza>();
    var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id);
    var pizza = redis.GetValue(pizzaKey);
}

Actualizar una pizza por ID (Simplemente un GET y SET)

using (var redisClient = new RedisClient())
{
    IRedisTypedClient<Pizza> redis = redisClient.As<Pizza>();
    var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id);
    var pizza = redis.GetValue(pizzaKey); // Get
    pizza.State = "Delivery"; // Update
    redis.SetEntry(pizzaKey, pizza); // Save
}

Mover a otra "lista" (tal vez:cuando una pizza cambia de estado)

using (var redisClient = new RedisClient())
{
    var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id);
    var deliveredKey = string.Format("pizzas:delivered:{0}", pizza.Id);
    redisClient.RenameKey(pizzaKey, deliveredKey);
}

Eliminar una pizza

using (var redisClient = new RedisClient())
{
    var pizzaKey = string.Format("pizzas:live:{0}", pizza.Id);
    redisClient.Remove(pizzaKey);
}

Lista de todas las pizzas en vivo

using (var redisClient = new RedisClient())
{
    var livePizzaKeys = redisClient.ScanAllKeys("pizzas:live:*").ToList();
    List<Pizza> livePizzas = redisClient.GetValues<Pizza>(livePizzaKeys);
}

Espero que esto ayude.