30

I know the KEYS command, but that only returns the keys (I'm guessing all of the keys with type String), and apparently sets aren't considered keys.

Is there a command for getting all of the sets in the database? What about other data types (hash, list, sorted set)?

http://redis.io/topics/data-types

beatgammit
  • 19,817
  • 19
  • 86
  • 129
  • See [answer below](https://stackoverflow.com/questions/7462457/how-can-i-get-all-of-the-sets-in-redis/59564727#59564727) on how to do this with `SCAN 0 TYPE set` (version 6) or an equivalent Lua script for prior versions – LeoMurillo Jan 13 '20 at 11:33

4 Answers4

36

I know the KEYS command, but that only returns the keys (I'm guessing all of the keys with type String), and apparently sets aren't considered keys.

KEYS command return results no matter what data type are your keys, since it searches key names. At the lowest level of abstraction each data type in redis is key/value based where value can be represented as one of several (advanced) data structures (string, hash, list, set, sorted set). You can see that KEYS command also work for sets in it's examples.

Is there a command for getting all of the sets in the database? What about other data types (hash, list, sorted set)?

As far as I know there is no dedicated command for this functionality and KEYS command is applied on entire data set of your database. However there is a TYPE command which can determine data type of specified key.

yojimbo87
  • 65,684
  • 25
  • 123
  • 131
  • 2
    Oops, I did `keys '*'`, not `keys *`. I was running this through redis-cli and was trying to avoid bash (sometimes I do `redis-cli keys '*'` or the like in bash instead of using redis-cli's interactive mode). Thanks for the answer though! – beatgammit Sep 18 '11 at 20:50
6

The answer was correct for its time, however this is supported from redis 2.8.0 - Check out SCAN

Amnon
  • 2,708
  • 2
  • 22
  • 21
  • 3
    How can you get a list of keys of type set using Scan? `SSCAN` command only iterates inside a key of type set – Emer Feb 24 '17 at 12:09
  • Exactly what I was looking for. Nice is you have forgotten names you have given to sets. – Josh Feb 17 '20 at 15:45
4

As of version 6.0, you can use SCAN 0 TYPE set. See https://redis.io/commands/scan#the-type-option

For versions prior to 6.0, you can use a Lua script to filter server-side, saving Round Trip Time (RTT) of doing TYPE calls back from the client.

EVAL "local result = redis.call('SCAN', ARGV[1], 'MATCH', ARGV[2]) local filtered = {} for _,key in ipairs(result[2]) do if redis.call('TYPE', key).ok == ARGV[3] then table.insert(filtered, key) end end result[2] = filtered return result" 0 0 * set

The parameters to the script are 0(numkeys) cursor matchPattern type. E.g. 0 0 * set

Here a friendly view of the Lua script:

local result = redis.call('SCAN', ARGV[1], 'MATCH', ARGV[2])
local filtered = {}
for _,key in ipairs(result[2]) do
    if redis.call('TYPE', key).ok == ARGV[3] then
        table.insert(filtered, key)
    end
end
result[2] = filtered
return result

The returned value is the same as with SCAN, just with the list of keys filtered by type.

As with SCAN, you need to call multiple times until the cursor returned is zero.

This approach is much better than using KEYS, as it won't block the server for a long time.

Next is the same script but with COUNT option, to do less or more work per call. The count should be greater than zero.

EVAL "local result = redis.call('SCAN', ARGV[1], 'MATCH', ARGV[2], 'COUNT', ARGV[3]) local filtered = {} for _,key in ipairs(result[2]) do if redis.call('TYPE', key).ok == ARGV[4] then table.insert(filtered, key) end end result[2] = filtered return result" 0 0 * 100 set

The parameters to the script are 0(numkeys) cursor matchPattern count type. E.g. 0 0 * 100 set

LeoMurillo
  • 6,048
  • 1
  • 19
  • 34
3

In cli-redis you can try and do:

KEYS *