skip to Main Content

I have redis cache with structure as below

private HashOperations<String, Long, Object> hashOperations;
//put data in cache
hashOperations.put("Key", 1, SomeObject);

I need to fetch data from the cache with pagination( first page 50 results, second page next 50 results and so on). How can this be implemented with spring data redis. Any help is appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    I found some work around for this online and used the same.

    @Override
        public List<Entity> findAll(final int pageNum, final int pageSize) {
            // Please validate the pageNum and pageSize in Controller that should be positive numbers
            int tmpIndex = 0;
            int tmpEndIndex = 0;
            final List<Entity> entities = new ArrayList<>();
            try (Cursor<Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(CACHE_KEY,
                    ScanOptions.scanOptions().match("*").build())) {
                while (cursor.hasNext()) {
                    if (tmpIndex >= pageNum && tmpEndIndex < pageSize) {
                        final Entry<Object, Object> entry = cursor.next();
                        final Entity entity = (Entity) entry.getValue();
                        entities.add(entity);
                        tmpIndex++;
                        tmpEndIndex++;
                        continue;
                    }
                    if (tmpEndIndex >= pageSize) {
                        break;
                    }
                    tmpIndex++;
                    cursor.next();
                }
            } catch (Exception ex) {
                if (LOGGER.isInfoEnabled()) {
                    LOGGER.info("Exception while fetching data from redis cache : " + ex);
                }
            }
            return entities;
        }
    

  2. If you need to guarantee the order of elements I think you will need some kind of sorted set (HSCAN is a good way to read an entire hash, but it doesn’t guarantee ordering of what it returns and it does not guarantee that there will be no duplicate data in what it returns). The only Redis data type which fits the description of a sorted set is: ZSET. ZSETs have fields similar to HASHes, but, instead of a string value, inside their fields they have a double “score” which is used to sort the fields.

    Thus, one thing you can do to get “hash paging” is to have a ZSET with all the same fields as your HASH. The HASH will contain the data in your fields and the ZSET will keep track of their ordering.

    ZSETs have a method called ZRANGE (documentation) which allows you to get a specific number of elements out of the set. For a “page” size of 50, it would look like this:

    # this gets you the "page" with the first 50 elements
    ZRANGE 0 50
    
    # this gets you the "page" with the second 50 elements
    ZRANGE 50 100
    
    # etc.
    

    So, to add some data to the zset/hash and then get a page you can do something like the following (pseudocode – might not compile):

    RedisTemplate<String, String> redisTemplate;
    
    String myKey = "exampleKey";
    
    // example of adding one record to the HASH + ZSET
    String myField = "field1";
    String myData = "123ABC";
    
    // in this example data inserted into the ZSET is ordered based on when it was inserted.
    // if you want to order it differently you can figure out your own way of coming up with scores
    redisTemplate.opsForZSet().add(myKey + "zset", myField, System.getCurrentTimeMillis());
    redisTemplate.opsForHash.put(mykey + "hash", myField, myData);
    
    // Get one page from the hash
    Set<String> first50hashFields = redisTemplate.opsForZSet().range(myKey + "zset", 0, 50);
    
    List<String> firstPage = LinkedList<>();
    for (String hashFieldKey : first50hashFields) {
         String hashFieldValue = redisTemplate.opsForHash().get(myKey + "hash", hashFieldKey);
    
         firstPage.add(hashFieldValue);
    }
    

    Hopefully that all-String example is enough to illustrate how this can be done.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search