snakesNbronies
snakesNbronies

Reputation: 3910

redis.py - sorting hashes by particular fields

I am using redis.py and was wondering how I can sort by a given field. I have read the documentation and attempted googling for examples, but haven't found anyhting.

In this case, I have a list of times and the corresponding temperatures. For a given range of 'time', say 1000 to 1100, I'd return the highest values for temp' for a given range of times, assigning it to the variable hightemp. Likewise, I would like to do it with lowtemp too.

Is it possible to do this within redis, as opposed to translating everything back into memory again, as would be the case if I sorted using python

import redis
red = redis.Redis()

red.hmset('temperature', {'time':900, 'temp':123})
red.hmset('temperature', {'time':930, 'temp':123})
red.hmset('temperature', {'time':1000, 'temp':121})
red.hmset('temperature', {'time':1030, 'temp':125})
red.hmset('temperature', {'time':1100, 'temp':126})
red.hmset('temperature', {'time':1130, 'temp':127})
red.hmset('temperature', {'time':1200, 'temp':128})

Upvotes: 4

Views: 3394

Answers (2)

Linus Thiel
Linus Thiel

Reputation: 39223

After pondering this for a while, I have to say it's tricky. The best solution I can come up with is this: Store the data in a sorted set, with time as score and time:temperature as value (to keep the values unique). Then you use ZRANGEBYSCORE to get the wanted subset:

redis 127.0.0.1:6379> zadd temperature 1000 1000:123
(integer) 1
redis 127.0.0.1:6379> zadd temperature 1050 1050:122
(integer) 1
redis 127.0.0.1:6379> zadd temperature 1100 1100:125
(integer) 1
redis 127.0.0.1:6379> zrangebyscore temperature 1000 1100
1) "1000:123"
2) "1050:122"
3) "1100:125"
redis 127.0.0.1:6379> 

These values, however, will be sorted on the score, i.e. the temperature. So you will have to sort the subset in the client instead:

# Result from Redis
result = ['1000:123', '1050:122', '1100:125']
# Weed out the temperatures
temperatures = [int(x.split(':')[1]) for x in result]
# Get max and min temperatures
max_temp, min_temp = max(temperatures), min(temperatures)

It's not super pretty, but it should work. What Lloyd Moore says in his answer is true, and you can sort by fields in hashes, but the SORT command won't let you select a subset easily. I will update this answer if I think of a better solution, or we'll just hope for a healthy discussion in the comments!

Edit: Changed from python sort() to max/min after Didier Speza's advice.

Upvotes: 6

Lloyd Moore
Lloyd Moore

Reputation: 3197

Each time you run red.hmset you are overwriting the value of temperature. Given that you want to sort these values, you need to give each entry a unique identifier.

temperature:1, temperature:2 ...

You could then use the redis sort command

SORT mylist BY weight_* GET object_*

on the external keys.

Hope that helps in some way. Let me know if you need more help.

Upvotes: 3

Related Questions