Redis
 sql >> Base de données >  >> NoSQL >> Redis

Mise à jour de la liste Redis de la pile de services

Éviter les listes :

Malheureusement, les listes Redis ne sont pas vraiment un bon choix dans cette situation. J'ai eu le même problème quand j'ai commencé à utiliser Redis, ils semblent être le choix évident ;). Les listes Redis sont utiles si vous les utilisez comme un ensemble en lecture seule, ou si vous voulez simplement faire apparaître et pousser, mais pas pour modifier un élément au milieu de la liste.

Vous pouvez "mettre à jour" des éléments dans une liste Redis si vous connaissez l'index de l'élément, mais cela nécessite de supprimer et réinsérer , et ce doit être par index, dont la détermination est horriblement inefficace. Il le fait en itérant la collection, car il n'existe aucun moyen natif de le faire, et ce n'est pas une bonne idée. Ceci est un extrait de l'IndexOf méthode de la 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;
}

Donc pour compléter votre code, ce serait :

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

Mais ce n'est pas une bonne façon de le gérer comme je l'ai dit. Il récupérera la liste des autres objets pizza puis les parcourra jusqu'à ce qu'il corresponde à l'index. Et deux opérations à mettre à jour ! :( Mieux vaut éviter les listes dans cette situation.

Solution :

Lorsque vous essayez d'accéder à la pizza par son identifiant, vous pouvez créer une clé de pizza unique pour chaque objet, cela vous permettra d'accéder directement à la pizza. Nous pourrions donc utiliser :

pizzas:live:{Id}

Exemples :

Créer une 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);
}

Obtenir une pizza par 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);
}

Mettre à jour une pizza par identifiant (Simplement un GET et 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
}

Déplacer vers une autre "liste" (peut-être :lorsqu'une pizza change d'état)

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

Supprimer une pizza

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

Répertorier toutes les pizzas en direct

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

J'espère que cela vous aidera.