Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Redis sort keys

I have the following keys in Redis(Spring Data Redis),

localhost>Keys *
"1+ { \"_id":"1", \"Name\" : \"C5796\" , \"Site\" : \"DRG1\"}"
"2+ { \"_id":"2", \"Name\" : \"CX1XE\" , \"Site\" : \"DG1\"}"
"3+ { \"_id":"3", \"Name\" : \"C553\" , \"Site\" : \"DG1\"}"

If I want to sort according to id/name/site, how can I do it in Spring Redis?

List<Object> keys = redistemplate.sort(SortQueryBuilder.sort("Customer").build());

and,

SortQuery<String> sort = SortQueryBuilder.sort(key).noSort().get(field).build(); 
List<?> keys = redistemplate.boundHashOps(key).getOperations().sort(sort);

are not working.

like image 309
ashK Avatar asked Feb 25 '16 18:02

ashK


People also ask

Can you sort in Redis?

Sorting in Redis is similar to sorting in other languages: we want to take a sequence of items and order them according to some comparison between elements. SORT allows us to sort LIST s, SET s, and ZSET s according to data in the LIST / SET / ZSET data stored in STRING keys, or even data stored in HASH es.

Are Redis Keys ordered?

Anyway results of keys or scan is not sorted in any manner, order of results related to internal memory structure of redis's hashtable.

How Redis works in spring boot?

Spring Boot will automatically configure a Redis-cache Manager but with default properties. We can modify this configuration and change it as per our requirement. Modifying the configurations gives us more control over the basic cache configuration.


2 Answers

The code is at the last of the post, if you are familiar with the principle of multi hset keys sort in redis, skip the following content and directly read the code.

Redis Sort is aimed to sort fields inside List/Set/Zset, but this method can be used to sort multi keys base on specified metric we want. We can use "sort" to sort multi hset keys by specified field, but there is limitation about the pattern of hset keys.
For example, if the pattern of hset keys is "hash{i}"(i is an integer), under this condition we can sort it.

127.0.0.1:6379> keys hash*
1) "hash3"
2) "hash2"
3) "hash1"

Take a look at the content of hash1:

127.0.0.1:6379> hgetall hash1
1) "id"
2) "24"
3) "name"
4) "kobe"

Every hash key contains two fields : "id", "name". If we want to sort these hset keys by its id. What should we do ?

First, add a set key named "myset". "myset" is a set key which contains members {"1", "2", "3"}.

127.0.0.1:6379> smembers myset
1) "1"
2) "2"
3) "3"

Then run the following command:

127.0.0.1:6379> SORT myset BY hash*->id GET hash*->id GET hash*->name
1) "3"
2) "wade"
3) "24"
4) "kobe"
5) "30"
6) "curry"

Eureka, sort hash{1-3} by its id.
Here is the code of using Spring Redis to do the job:

public static String getRandomStr() {
    return String.valueOf(new Random().nextInt(100));
}

public static void redisTemplateSort(RedisTemplate redisTemplate) {
    String sortKey = "sortKey";

    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

    redisTemplate.setKeySerializer(stringRedisSerializer);
    redisTemplate.setValueSerializer(stringRedisSerializer);
    redisTemplate.setHashKeySerializer(stringRedisSerializer);
    redisTemplate.setHashValueSerializer(stringRedisSerializer);

    redisTemplate.delete(sortKey);
    if (!redisTemplate.hasKey(sortKey)) {
        for (int i = 0; i < 10; i++) {
            redisTemplate.boundSetOps(sortKey).add(String.valueOf(i));
            String hashKey = "hash" + i,
                    strId = String.valueOf(i),
                    strName = getRandomStr(),
                    strSite = getRandomStr();
            redisTemplate.boundHashOps(hashKey).put("_id", strId);
            redisTemplate.boundHashOps(hashKey).put("Name", strName);
            redisTemplate.boundHashOps(hashKey).put("Site", strSite);

            System.out.printf("%s : {\"_id\": %s, \"Name\": %s, \"Site\", %s}\n",
                    hashKey, strId, strName, strSite);
        }
    }

    SortQuery<String> sortQuery = SortQueryBuilder.sort(sortKey).by("hash*->Name")
            .get("hash*->_id").get("hash*->Name").get("hash*->Site").build();
    List<String> sortRslt = redisTemplate.sort(sortQuery);

    for (int i = 0; i < sortRslt.size(); ) {
        System.out.printf("{\"_id\": %s, \"Name\": %s, \"Site\", %s}\n", sortRslt.get(i+2), sortRslt.get(i+1), sortRslt.get(i));
        i += 3;
    }
}

Result of running redisTemplateSort(redisTemplate)(as sort by name in the code) :

hash0 : {"_id": 0, "Name": 59, "Site", 60}
hash1 : {"_id": 1, "Name": 37, "Site", 57}
hash2 : {"_id": 2, "Name": 6, "Site", 40}
hash3 : {"_id": 3, "Name": 91, "Site", 58}
hash4 : {"_id": 4, "Name": 39, "Site", 32}
hash5 : {"_id": 5, "Name": 27, "Site", 82}
hash6 : {"_id": 6, "Name": 43, "Site", 10}
hash7 : {"_id": 7, "Name": 17, "Site", 55}
hash8 : {"_id": 8, "Name": 14, "Site", 91}
hash9 : {"_id": 9, "Name": 39, "Site", 91}
{"_id": 40, "Name": 6, "Site", 2}
{"_id": 91, "Name": 14, "Site", 8}
{"_id": 55, "Name": 17, "Site", 7}
{"_id": 82, "Name": 27, "Site", 5}
{"_id": 57, "Name": 37, "Site", 1}
{"_id": 32, "Name": 39, "Site", 4}
{"_id": 91, "Name": 39, "Site", 9}
{"_id": 10, "Name": 43, "Site", 6}
{"_id": 60, "Name": 59, "Site", 0}
{"_id": 58, "Name": 91, "Site", 3}
like image 104
sel-fish Avatar answered Oct 22 '22 22:10

sel-fish


I don't know about spring data redis. Let me give you a sample to achieve this in naive Redis. Let us say you have hash, which has id, name and site. and i have a list representing the keys of that hash.

My structure will be like :

lpush("Values",1);  


hset("hash_1","id","1"),hset("hash_1","Name","C5796"),hset("hash_1","Site","DRG1")

for second hash
lpush("Values",2);
...

Similarly for all the values you want to set in hash. Now for sorting you do like this

SORT "Values" BY hash_*->id get hash_*->id get hash_*->name get hash_*->site

this will return you ascending sorted hashmaps result based on id. similarly you can do for names/site. For more info about sorting in redis : http://redis.io/commands/sort

like image 36
Karthikeyan Gopall Avatar answered Oct 22 '22 22:10

Karthikeyan Gopall