Redis
 sql >> Database >  >> NoSQL >> Redis

Aggiornamento dell'elenco Redis dello stack di servizi

Evita elenchi:

Sfortunatamente le liste Redis sono non proprio una buona scelta in questa situazione. Ho avuto lo stesso problema quando ho iniziato a usare Redis, sembrano la scelta più ovvia;). Le liste Redis sono utili se le stai usando come set di sola lettura, o se vuoi semplicemente fare clic e premere, ma non per modificare un elemento nel mezzo dell'elenco.

Puoi "aggiornare" gli elementi in un elenco Redis se conosci l'indice dell'elemento, ma è necessario rimuovere e reinserire , e deve essere per indice, la cui determinazione è orribilmente inefficiente. Lo fa iterando la raccolta, perché non esiste un modo nativo per farlo e questa non è una buona idea. Questo è un frammento di IndexOf metodo del 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;
}

Quindi, per completare il tuo codice, sarebbe:

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);
    }                   
}

Ma questo non è un bel modo di gestirlo come ho detto. Recupererà l'elenco degli altri oggetti pizza, quindi eseguirà un'iterazione su di essi finché non corrisponderà all'indice. E due operazioni per aggiornare! :( Meglio evitare le liste in questa situazione.

Soluzione:

Mentre stai tentando di accedere alla pizza tramite il suo Id, puoi creare una chiave pizza univoca per ogni oggetto, questo ti consentirà di accedere direttamente alla pizza. Quindi potremmo usare:

pizzas:live:{Id}

Esempi:

Crea 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);
}

Prendi una pizza per ID

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);
}

Aggiorna una pizza in base all'ID (Semplicemente un GET e 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
}

Sposta in un altro "elenco" (forse:quando una pizza cambia stato)

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);
}

Elimina una pizza

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

Elenca tutte le pizze dal vivo

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

Spero che questo aiuti.