web-dev-qa-db-ja.com

リスト要素をRedisキャッシュに保存する方法

C#redisキャッシュにStackExchange.Redisを使用しました。

cache.StringSet("Key1", CustomerObject);

しかし、私は次のようなデータを保存したい

cache.StringSet("Key1", ListOfCustomer);

1つのキーにすべての顧客リストが保存され、そのリスト内でも顧客データの検索、グループ化、フィルタリングが簡単になります

ServiceStack.RedisまたはStackExchange.Redisを使用して回答を歓迎します

15
Neo

ServiceStack.Redis 高レベル IRedisTypedClient Typed API を使用して、リッチPOCOタイプを管理できます。

まず、次の機能を備えたお客様向けの型指定されたRedisクライアントを取得します。

var redisCustomers = redis.As<Customer>();

これにより、顧客POCOを管理するための高レベルの型付きAPIが解決され、単一の顧客を次のように永続化できます。

redisCustomers.SetEntry("Customer1", CustomerObject);

または、以下の顧客のリスト:

redisCustomers.Lists["Customers"].AddRange(ListOfCustomer);
8
mythz

Stackechange.Redis を使用する場合、そのAPIでListメソッドを使用できます。以下は、Redisリストを使用してアイテムを保存するIListの単純な実装です。

リストAPIメソッドのいくつかを理解するのに役立つことを願っています:

public class RedisList<T> : IList<T>
{
    private static ConnectionMultiplexer _cnn;
    private string key;
    public RedisList(string key)
    {
        this.key = key;
        _cnn = ConnectionMultiplexer.Connect("localhost");
    }
    private IDatabase GetRedisDb()
    {
        return _cnn.GetDatabase();
    }
    private string Serialize(object obj)
    {
        return JsonConvert.SerializeObject(obj);
    }
    private T Deserialize<T>(string serialized)
    {
        return JsonConvert.DeserializeObject<T>(serialized);
    }
    public void Insert(int index, T item)
    {
        var db = GetRedisDb();
        var before = db.ListGetByIndex(key, index);
        db.ListInsertBefore(key, before, Serialize(item));
    }
    public void RemoveAt(int index)
    {
        var db = GetRedisDb();
        var value = db.ListGetByIndex(key, index);
        if (!value.IsNull)
        {
            db.ListRemove(key, value);
        }
    }
    public T this[int index]
    {
        get
        {
            var value = GetRedisDb().ListGetByIndex(key, index);
            return Deserialize<T>(value.ToString());
        }
        set
        {
            Insert(index, value);
        }
    }
    public void Add(T item)
    {
        GetRedisDb().ListRightPush(key, Serialize(item));
    }
    public void Clear()
    {
        GetRedisDb().KeyDelete(key);
    }
    public bool Contains(T item)
    {
        for (int i = 0; i < Count; i++)
        {
            if (GetRedisDb().ListGetByIndex(key, i).ToString().Equals(Serialize(item)))
            {
                return true;
            }
        }
        return false;
    }
    public void CopyTo(T[] array, int arrayIndex)
    {
        GetRedisDb().ListRange(key).CopyTo(array, arrayIndex);
    }
    public int IndexOf(T item)
    {
        for (int i = 0; i < Count; i++)
        {
            if (GetRedisDb().ListGetByIndex(key, i).ToString().Equals(Serialize(item)))
            {
                return i;
            }
        }
        return -1;
    }
    public int Count
    {
        get { return (int)GetRedisDb().ListLength(key); }
    }
    public bool IsReadOnly
    {
        get { return false; }
    }
    public bool Remove(T item)
    {
        return GetRedisDb().ListRemove(key, Serialize(item)) > 0;
    }
    public IEnumerator<T> GetEnumerator()
    {
        for (int i = 0; i < this.Count; i++)
        {
            yield return Deserialize<T>(GetRedisDb().ListGetByIndex(key, i).ToString());
        }
    }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        for (int i = 0; i < this.Count; i++)
        {
            yield return Deserialize<T>(GetRedisDb().ListGetByIndex(key, i).ToString());
        }
    }
}

シリアル化にNewtonsoft.Jsonを使用していることに注意してください。次のnu-getパッケージが必要です。

Install-Package Newtonsoft.Json
Install-Package StackExchange.Redis

質問とコメントを読んだ後、キーで要素にアクセスしたいので、値に関連付けられたフィールドで構成されるマップである Redis Hashes を探していると思います。

そのため、すべての顧客を含むハッシュのRedisキーを持つことができます。各顧客はフィールドに関連付けられた値です。 CustomerIdをフィールドとして選択できるため、O(1)のIDで顧客を取得できます。

IDictionaryを実装することは、それが機能するのを見る良い方法だと思います。そのため、RedisListに似ていますが、Redisハッシュを使用するRedisDictionaryクラスは次のようになります。

public class RedisDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
    private static ConnectionMultiplexer _cnn;
    private string _redisKey;
    public RedisDictionary(string redisKey)
    {
        _redisKey = redisKey;
        _cnn = ConnectionMultiplexer.Connect("localhost");
    }
    private IDatabase GetRedisDb()
    {
        return _cnn.GetDatabase();
    }
    private string Serialize(object obj)
    {
        return JsonConvert.SerializeObject(obj);
    }
    private T Deserialize<T>(string serialized)
    {
        return JsonConvert.DeserializeObject<T>(serialized);
    }
    public void Add(TKey key, TValue value)
    {
        GetRedisDb().HashSet(_redisKey, Serialize(key), Serialize(value));
    }
    public bool ContainsKey(TKey key)
    {
        return GetRedisDb().HashExists(_redisKey, Serialize(key));
    }
    public bool Remove(TKey key)
    {
        return GetRedisDb().HashDelete(_redisKey, Serialize(key));
    }
    public bool TryGetValue(TKey key, out TValue value)
    {
        var redisValue = GetRedisDb().HashGet(_redisKey, Serialize(key));
        if (redisValue.IsNull)
        {
            value = default(TValue);
            return false;
        }
        value = Deserialize<TValue>(redisValue.ToString());
        return true;
    }
    public ICollection<TValue> Values
    {
        get { return new Collection<TValue>(GetRedisDb().HashValues(_redisKey).Select(h => Deserialize<TValue>(h.ToString())).ToList()); }
    }
    public ICollection<TKey> Keys
    {
        get { return new Collection<TKey>(GetRedisDb().HashKeys(_redisKey).Select(h => Deserialize<TKey>(h.ToString())).ToList()); }
    }
    public TValue this[TKey key]
    {
        get
        {
            var redisValue = GetRedisDb().HashGet(_redisKey, Serialize(key));
            return redisValue.IsNull ? default(TValue) : Deserialize<TValue>(redisValue.ToString());
        }
        set
        {
            Add(key, value);
        }
    }
    public void Add(KeyValuePair<TKey, TValue> item)
    {
        Add(item.Key, item.Value);
    }
    public void Clear()
    {
        GetRedisDb().KeyDelete(_redisKey);
    }
    public bool Contains(KeyValuePair<TKey, TValue> item)
    {
        return GetRedisDb().HashExists(_redisKey, Serialize(item.Key));
    }
    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
    {
        GetRedisDb().HashGetAll(_redisKey).CopyTo(array, arrayIndex);
    }
    public int Count
    {
        get { return (int)GetRedisDb().HashLength(_redisKey); }
    }
    public bool IsReadOnly
    {
        get { return false; }
    }
    public bool Remove(KeyValuePair<TKey, TValue> item)
    {
        return Remove(item.Key);
    }
    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        var db = GetRedisDb();
        foreach (var hashKey in db.HashKeys(_redisKey))
        {
            var redisValue = db.HashGet(_redisKey, hashKey);
            yield return new KeyValuePair<TKey, TValue>(Deserialize<TKey>(hashKey.ToString()), Deserialize<TValue>(redisValue.ToString()));
        }
    }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        yield return GetEnumerator();
    }
    public void AddMultiple(IEnumerable<KeyValuePair<TKey, TValue>> items)
    {
        GetRedisDb()
            .HashSet(_redisKey, items.Select(i => new HashEntry(Serialize(i.Key), Serialize(i.Value))).ToArray());
    }
}

そして、それを使用するいくつかの例があります:

// Insert customers to the cache            
var customers = new RedisDictionary<int, Customer>("customers");
customers.Add(100, new Customer() { Id = 100, Name = "John" });
customers.Add(200, new Customer() { Id = 200, Name = "Peter" });

// Or if you have a list of customers retrieved from DB:
IList<Customer> customerListFromDb;
customers.AddMultiple(customerListFromDb.ToDictionary(k => k.Id));

// Query a customer by its id
var customers = new RedisDictionary<int, Customer>("customers");
Customer customer100 = customers[100];

更新(2015年10月)

これらのコレクションのより良い実装は、 CachingFramework.Redis ライブラリにあります。

ここ はコードです。

27
thepirat000

StackExchange.Redisには、値のリストとセットを処理するための関数があらかじめ定義されています。

IDatabaseオブジェクトの取得:

string cacheConnection = Utils.Sections.Storage.RedisCache.ConnectionString;

IDatabase cache = ConnectionMultiplexer.Connect(cacheConnection).GetDatabase();

リストのメソッド:

cache.ListLeftPushAsync(key、values)->要素のリストのいずれかをプッシュする

cache.ListRangeAsync(key、startIndex、endIndex)->値のリストを取得

cache.KeyExpire(key、timspan)

その他のメソッドについては、StackExchange.Redisをパッケージ化してください。追加のNugetパッケージを含める必要はありません。

0
Happy Mittal