使用外部 key 進行排序
有時候你會希望使用外部的 key 作爲權重來比較元素,代替默認的對比方法。
假設現在有用戶(user)數據如下:
id name level 1 admin 9999 2 huangz 10 59230 jack 3 222 hacker 9999
# 先將要使用的數據加入到數據庫中
# admin
redis> LPUSH user_id 1
(integer) 1
redis> SET user_name_1 admin
OK
redis> SET user_level_1 9999
OK
# huangz
redis> LPUSH user_id 2
(integer) 2
redis> SET user_name_2 huangz
OK
redis> SET user_level_2 10
OK
# jack
redis> LPUSH user_id 59230
(integer) 3
redis> SET user_name_59230 jack
OK
redis> SET user_level_59230 3
OK
# hacker
redis> LPUSH user_id 222
(integer) 4
redis> SET user_name_222 hacker
OK
redis> SET user_level_222 9999
OK
如果希望按 level 從大到小排序 user_id ,可以使用以下命令:
redis> SORT user_id BY user_level_* DESC
1) "222" # hacker
2) "1" # admin
3) "2" # huangz
4) "59230" # jack
但是有時候只是返回相應的 id 沒有什麼用,你可能更希望排序後返回 id 對應的用戶名,這樣更友好一點,使用 GET 選項可以做到這一點:
redis> SORT user_id BY user_level_* DESC GET user_name_*
1) "hacker"
2) "admin"
3) "huangz"
4) "jack"
http://manual.csser.com/redis/key/sort.html
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>