redis sort 使用外部key排序

使用外部 key 进行排序

有时候你会希望使用外部的 key 作为权重来比较元素,代替默认的对比方法。

假设现在有用户(user)数据如下:

id name level
1 admin 9999
2 huangz 10
59230 jack 3
222 hacker 9999
id 数据保存在  key 名为  user_id 的列表中。
name 数据保存在  key 名为  user_name_{id} 的列表中
level 数据保存在  user_level_{id} 的  key 中。
# 先将要使用的数据加入到数据库中

# 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



 
 
>>> conn.rpush('sort-input', 23, 15, 110, 7) #A
4 #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) #D
1L #D
>>> conn.hset('d-15', 'field', 1) #D
1L #D
>>> conn.hset('d-23', 'field', 9) #D
1L #D
>>> conn.hset('d-110', 'field', 3) #D
1L #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

example.com/level1

example.com/level1/level2

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

example.com/level1

example.com/level1/level2

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值