ashK
ashK

Reputation: 733

Spring Redis Hash operations SCAN

I'm doing Spring Redis, I put the key as

redistemplate.opsForHash().put("Customer", Customer.class, List<Customers>)

I want to search from the List<>,

ScanOptions options = ScanOptions.scanOptions().match(pattern).count(1).build();

Cursor<Entry<Object, Object>> keys = redistemplate.opsForHash().scan("Customer", options);

Also not working. Please help!!

Upvotes: 5

Views: 11774

Answers (3)

Ming Arron
Ming Arron

Reputation: 21

When use spring redistemplate, try below to iterate fields and values in a redis hash

  /**
   * hScan provided by redis template is for iterating fields and values within a redis HashMap, not among keys
   * @param key
   * @return
   */
  public Map<String, String> hscanAll(final String key) {
    return hscanPattern(key, "*");
  }

  /**
   * Returns the map with fields that match the given {@Code fieldPattern} and values from the HashMap of the given redis {@Code key}
   * @param key
   * @param fieldPattern
   * @return
   */
  public Map<String, String> hscanPattern(final String key, final String fieldPattern) {
    return (Map<String, String>)
        redisTemplate.execute(
            (RedisCallback<Map<String, String>>)
                connection -> {
                  Map<String, String> map = new HashMap<>();
                  try (Cursor<Map.Entry<byte[], byte[]>> cursor =
                      connection.hScan(
                          key.getBytes(),
                          new ScanOptions.ScanOptionsBuilder().match(fieldPattern).count(200).build())) {

                    while (cursor.hasNext()) {
                      Map.Entry<byte[], byte[]> entry = cursor.next();
                      map.put(
                          new String(entry.getKey(), "Utf-8"),
                          new String(entry.getValue(), "Utf-8"));
                    }
                  } catch (Exception e) {
                    log.error(e.getMessage(), e);
                    throw new RuntimeException(e);
                  }
                  return map;
                });
  }

Upvotes: 1

ZW Q
ZW Q

Reputation: 11

I came across this issue today, and I find my redis server version is redis_version:2.6.16, and the redis.io says that this command is available since 2.8.0. See: https://redis.io/commands/scan.

Hope that can help you!

Upvotes: 1

Nebras
Nebras

Reputation: 636

First of all, the scan operation matches keye not match the values. When using a Hash to store values it should be as below: redisTemplate.opsForHash().put("key", keyInsideHash, value); So the actual key of a Redis record is key (You use it to fetch the Hash). keyInsideHash is the key of actual value you need to store. So first to get the hash then get the value from it. For example: redisTemplate.opsForHash().put("customerKey1", "FirstName", "MyFirstName"); and redisTemplate.opsForHash().put("customerKey1", "LastName", "MyLastName");. in this example we store in the same hash with key "customerKey1" two entries ["FirstName","MyFirstName"] and ["LastName", "MyLastName"] . In your case you have a List instead of "MyFirstName". If you need to scan a Hash, you do as below (scanning the keys inside the hash not values):

saveToDbCacheRedisTemplate.execute(new RedisCallback<List<String>>() {

            @Override
            public List<String> doInRedis(RedisConnection connection) throws DataAccessException {
                ScanOptions options = ScanOptions.scanOptions().match("pattern").count(1).build();;
                Cursor<Entry<byte[], byte[]>> entries = connection.hScan("customerKey1".getBytes(), options);
                List<String> result = new ArrayList<String>();
                if(entries!=null)
                    while(entries.hasNext()){
                        Entry<byte[], byte[]> entry = entries.next();
                        byte[] actualValue = entry.getValue();
                        result.add(new String(actualValue));
                    }

                return result;
            }

        });

Upvotes: 4

Related Questions