使用外部 key 进行排序
有时候你会希望使用外部的 key 作为权重来比较元素,代替默认的对比方法。
假设现在有用户(user)数据如下:
id name level 1 admin 9999 2 huangz 10 59230 jack 3 222 hacker 9999
如果希望按 level 从大到小排序 user_id ,可以使用以下命令:
但是有时候只是返回相应的 id 没有什么用,你可能更希望排序后返回 id 对应的用户名,这样更友好一点,使用 GET 选项可以做到这一点:
http://manual.csser.com/redis/key/sort.html
>>> conn.rpush('sort-input', 23, 15, 110, 7) #A4 #A>>> conn.sort('sort-input') #B['7', '15', '23', '110'] #B>>> conn.sort('sort-input', alpha=True) #C['110', '15', '23', '7'] #C>>> conn.hset('d-7', 'field', 5) #D1L #D>>> conn.hset('d-15', 'field', 1) #D1L #D>>> conn.hset('d-23', 'field', 9) #D1L #D>>> conn.hset('d-110', 'field', 3) #D1L #D>>> conn.sort('sort-input', by='d-*->field') #E['15', '110', '7', '23'] #E>>> conn.sort('sort-input', by='d-*->field', get='d-*->field') #F['1', '3', '5', '9']
This is just off thetop of my head / crazy / no guarantee of
correctness orperformance, just my attempt at minimizing roundtrips:
1) Store each path with a score, doesn't really matterhow. Lets go
with a hash with the url as the key, and the fields xand y with the
score, like this:
path:example.com {x: 10, y: 20}
path:example.com/level1 {x: 22, y: 41}
... etc
2) Store an index of each path returning a score in asorted set
(score 1 so it is sorted alphanumericly), lets call it"paths":
example.com/level1/level2/level3
example.com/level1/level2/level31
3) Each request will need a unique id, a uuid wouldwork. Split the
requested url into paths of different depths. forexample:
split http://example.com/level1/level2/level3/anythingelse/somefile.html into:
example.com/level1/level2/level3
example.com/level1/level2/level3/anythingelse
example.com/level1/level2/level3/anythingelse/somefile.html
4) Now send the request to the redis server:
MULTI
// add each path to a unique sorted set
ZADD req:uuid 1 example.com
ZADD req:uuid 1 example.com/level1
ZADD req:uuid 1 example.com/level1/level2
ZADD req:uuid 1 example.com/level1/level2/level3
ZADD req:uuid 1 example.com/level1/level2/level3/anythingelse
ZADD req:uuid 1 example.com/level1/level2/level3/anythingelse/somefile.html
// store all the intersecting paths in another sortedset
ZINTERSTORE res:uuid 2 paths req:uuid
// get the last matching path from the intersection(this is the only
value you need)
ZREVRANK res:uuid 0
//clean up
DEL req:uuid res:uuid
EXEC
The return value for the ZREVRANK command should bethe deepest path
that matches the request. From there you can query forthe scores. It
might be possible to do this all in one request bydoing this instead
of the ZREVRANK:
SORT res:uuid LIMIT 0 1 GET # GET path:*->x GETpath:*->y ALPHA DESC
Using SORT might also allow you to just use plain setsinstead of
sorted sets since it will be sorting them anyways,which would save on
memory.
--
Derek
来自 <https://groups.google.com/forum/#!topic/redis-db/v9bdyGz8ZAM>