Redis Command To Sort Keys
Asked Answered
S

3

12

The Redis command keys * will return a list of all keys and scan 0 is a more recent way to do something similar, but with less blocking. Do any commands exist that can sort the keys found, such as alphabetically, numerically, by creation timestamp, etc.?

Example of standard and fancy command sought:

standard keys post:* command:

post:2150
post:2400
post:1001
post:1006

fancy command to sort the keys alphabetically:

post:1001
post:1006
post:2150
post:2400
Skyward answered 18/4, 2015 at 0:46 Comment(1)
Are you looking for this?Torosian
E
14

Redis returns keys, using KEYS (don't use it in production!) or SCAN, unordered. There is no "fancy" API to return them sorted but you can do it in the client application.

Eating answered 18/4, 2015 at 9:53 Comment(4)
Thanks for confirming this to be the case. I wasn't sure if I missed something in the Redis spec. Yes, that's what I am currently doing, sorting the results in the client.Skyward
Excellent - if you're doing a lot of these, you can consider moving (some) the logic to Redis via the use of (Sorted) Sets, the SORT command and/or Lua scripts. OTOH, using Redis' too much RAM/CPU/NW can become another issue, so there's definitely a tradeoff. Personally, if you only need to sort the keys for the client, I'd keep that work there (unless the client's performance is an issue ;))Eating
Completely agree on the client offload and am totally leveraging the z commands for shuffling data by score. I don't work for Redis, but have to say its features are a whole new architectural paradigm and it's a game changer.Skyward
if you need a specific one time thing, you can run the unix command to sort output of SCANPlanometer
P
13

You can always use your unix commands which works perfectly

redis-cli --scan --pattern yourpattern* | sort

Planometer answered 21/11, 2019 at 12:38 Comment(0)
A
1

For completeness sake:

You technically can do this within the context of Redis, using the EVAL command.

This would get all keys according to the post:* pattern, then sort the keys, and use them to MGET all the items.

EVAL "local keys = redis.call('KEYS','post:*');
      if (table.getn(keys) == 0) then return {} end;
      table.sort(keys);
      return redis.call('MGET',unpack(keys));"

This approach can increase performance, but manipulating Redis using LUA scripts might feel inelegant.

There are also issues with the KEYS command, and some safety considerations with EVAL of course.

I would say that the "Proper Redis Way" to solve this, would be to design a "composite data structure" around the use case:

// a scoreless sorted set can be used as an index
SET post:1500 <value>
ZADD posts_index 0 post:1500

// Whenever you need a sorted (range) of items, you first check the index 
ZRANGE posts_index - + BYLEX 
ZRANGE posts_index [posts:1000 (posts:2000 BYLEX 

The sorted set posts_index is just a set of all the keys in the post "namespace". Of course, if you set TTLs or remove items from cache, you will need to manage this for the posts_index set as well.

The result of ZRANGE is sorted, and can be used to GET/MGET items

The advantage of this over client-side sorting is performance: It's pre-sorted, and you can split it into ranges, use cursors to only hold a few items in memory at a time, etc.

Anosmia answered 15/4, 2022 at 14:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.