How to store list element in Redis cache

redis list
stackexchange.redis add list
redis hash example
azure redis cache console commands
how to store object in redis cache
redis query
how to store data in redis
store object in redis c#

I have used StackExchange.Redis for c# redis cache.

cache.StringSet("Key1", CustomerObject);

but I want to store data like

cache.StringSet("Key1", ListOfCustomer);

so that one key has all Customer List stored and it is easy to search,group,filter customer Data also inside that List

Answers are welcome using ServiceStack.Redis or StackExchange.Redis

You can use ServiceStack.Redis high-level IRedisTypedClient Typed API for managing rich POCO Types.

First get a typed Redis client for Customers with:

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

Which will resolve a high-level typed API for managing Customer POCO's that then lets you persist a single Customer with:

redisCustomers.SetEntry("Customer1", CustomerObject);

Or a list of Customers with:

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

Data types – Redis, It is possible to add elements to a Redis List pushing new elements on the head (​on Every hash can store up to 232 - 1 field-value pairs (more than 4 billion). IDatabase cache = ConnectionMultiplexer.Connect(cacheConnection).GetDatabase(); methods of list : cache.ListLeftPushAsync(key, values) -> push one of list of elements. cache.ListRangeAsync(key, startIndex, endIndex) -> get list of values. cache.KeyExpire(key, timspan) please package StackExchange.Redis for more methods.

If you use Stackechange.Redis, you can use the List methods on its API. Here is a naive implementation of IList using a redis list to store the items.

Hopefully it can help you to understand some of the list API methods:

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

Note the use of Newtonsoft.Json for the serialization. You will need the following nu-get packages:

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

After reading your question and comments, since you want to access elements by key, I think you're looking for Redis Hashes, which are maps composed of fields associated with values.

So you can have a Redis Key for a Hash containing all your Customers, each one being a Value associated to a Field. You can choose the CustomerId as the Field, so you can then get a customer by its id in O(1).

I think implementing IDictionary is a good way to see it working. So a RedisDictionary class similar to the RedisList but using a Redis Hash could be:

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

And here are some examples to use it:

// 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];
Update (Oct 2015)

A better implementation of these collections can be found on CachingFramework.Redis library.

Here is the code.

How To Manage Lists in Redis, Redis is an open-source, in-memory key-value data store. Redis reads lists from left to right, and you can add new list elements to the head of  cache.ListLeftPushAsync(key, values) -> push one of list of elements. cache.ListRangeAsync(key, startIndex, endIndex) -> get list of values. cache.KeyExpire(key, timspan) please package StackExchange.Redis for more methods. You don't need to include any extra nuget package.

StackExchange.Redis has already predefined functions to deal with list and set of values.

Get IDatabase object :

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

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

methods of list :

cache.ListLeftPushAsync(key, values) -> push one of list of elements

cache.ListRangeAsync(key, startIndex, endIndex) -> get list of values

cache.KeyExpire(key, timspan)

please package StackExchange.Redis for more methods. You don't need to include any extra nuget package.

1.2.2 Lists in Redis, LISTs in Redis store an ordered sequence of strings. Learn about RPUSH, LRANGE, LINDEX, and LPOP commands in Redis. 2.1 Login and cookie caching · 2.2 Shopping carts in Redis · 2.3 Web page caching · 2.4 Database row caching Figure 1.2An example of a LIST with three items under the key, list-key . Redis is simple key value store.it is often referred to as an NoSQL database. it can be used as database cache and message broker. it stores data structure like string, hashes , lists , sets and sorted sets and you can perform atomic operation on it.

How To store reference type object (or List) in redis Cache · Issue , Since you mention lists (which rules out hashes), the thing that leaps to mind here is serialization. SE.Redis very deliberately does not express  an extension method that adds a helper method onto any of the SE.Redis APIs On 29 Dec 2015 10:01 a.m., "Kamran Shahid" notifications@github.com wrote: Is there any possibility that i can to store reference type object (or List) in redis Cache (without using further extension) — Reply to this email directly or view it on GitHub #325.

Storing complex data structures in Redis, Alternatively they could be stored in Redis Lists with lpush . include RedisAppJoin # cache records users = User.some_scope.only(:first_name, :​last_name class ProcessStack def perform while REDIS.llen('stack') > 0 item  4 minute read. Redis is a super fast, in-memory, advanced key-value store capable of lightning quick operations. While it is commonly used for tasks such as caching, realtime leaderboards, analytics, and similar, in this post I am going to explain how you can use redis for storing and efficiently querying millions of objects.

Redis for .NET Developers - Redis List Datatype, Just like in LinkedList in C#, Redis can store items at Head or Tail of a List. The nice thing about them is that the insertion speed is just O(1), but  You can add elements in Redis lists in the head or the tail of the list. Maximum length of a list is 2 32 - 1 elements (4294967295, more than 4 billion of elements per list). Example. In the above example, three values are inserted in Redis list named ‘tutorials’ by the command LPUSH.

Comments
  • Be aware of the ServiceStack.Redis limits for free usage
  • @thepirat000 how to use list using ServiceStack.Redis?
  • Depends on how do you want to access the list. Will you always retrieve the entire list from redis, or do you want to handle items individually?
  • actually both. for filtered values i will use individual for all customer show i want entire list items
  • NOTE: When I read "ServiceStack.Redis" was not free, I got worried because I read it as "StackExchange.Redis" (which is in fact free MIT license). Maybe someone else could make that mistake, just wanted to add this warning because the names are similar and easy to mistake when reading quickly.
  • thanks a lot any example sample for the same with Customer list values with one key ?
  • Thanks a lot same as my requirement is stored customer values into one customer list and i able to get values from list by passing customer name also
  • unble to get all customer elements using customers.AddMultiple(customerListFromDb.ToDictionary(k => k.Id));
  • What if Id is autogenerated during Add, and we don't know Id in advance. In that case, how to Add to hash?
  • You must provide a key (field) to insert an element to a Redis Hash. You could use a key different from your Id