【Redis】【Python】集合数据类型的使用,应用和问题

本文原题: Redis 有序集合(sorted set)数据类型的使用,应用和问题
对标题同步正文内容更新。

1 redis-cli 操作数据库 - n/a

2 Python 操作 Redis (redis-py 库)

2.0 安装

$ pip install redis

2.1 集合 S

n/a
本节使用 优快云 的 user id 作为例子。
想象将 优快云 的所有注册过的用户对应的唯一 ID 放在一个 redis 集合中,这个 redis 集合 key-name 使用 userids 表示。

连接 redis 数据库:

>>> from redis import Redis
>>> db = Redis(host='localhost', port=6379, db=0)
2.1.1 SMEMBERS

使用 .smembers 获取一个 key-name 的所有元素,python 中使用 set 类型返回(编码过)。

我们获取一个在 redis 数据库中还不存在的集合(名):

>>> db.smembers('userids')
set()

>>> 

对于不存在的集合,也就意味着内容为空,可以看到 redis-py 返回空的 Python set 类型。

假设过去已经为 userids 集合添加过内容:

>>> db.smembers('userids')
{b'qq_29757283'}

>>>

可以看到,redis 返回了一个编码过的 user id。

这个 user id 就是本人的 优快云 账号 ID,可以在浏览器的地址栏看出:
n/a

2.1.2 SADD

为 redis 集合添加内容

>>> db.smembers('userids')
set()

>>> db.sadd('userids', 'qq_29757283')
1

>>> db.smembers('userids')
{b'qq_29757283'}

>>> 

可以看到保存的时候会自动编码,那么如果添加一个编码过的 user id 会如何:

>>> db.sadd('userids', 'stpeace'.encode('utf-8'))
1

>>> db.smembers('userids')
{b'qq_29757283', b'stpeace'}

>>> 

如果添加一个已经存在了的用户会如何:

>>> db.sadd('userids', 'qq_29757283')
0

>>>

可以看到返回值为 0,说明说没有新添加的 user id。

编码会如何影响你的代码:

>>> smembers = db.smembers('userids')
>>> smembers
{b'qq_29757283', b'stpeace'}

>>> tmpl = ['qq_29757283', 'stpeace']
>>> tmps = set(tmpl)
>>> tmps
{'qq_29757283', 'stpeace'}

>>> smembers == tmps
False

>>> encode_tmpl = [_.encode('utf-8') for _ in tmpl]
>>> encode_tmps = set(encode_tmpl)
>>> smembers == encode_tmps
True

>>>

当然,这不仅影响了 python 集合的 __eq__ (比较两个对象是否相等)操作。同时 python 集合的其它数学运算也会收到影响。

如果对 python 集合运算过之后,想要将 diff 的集合“添加”到 redis 集合中:

>>> diff_set
{b'userid_1', b'userid_2'}

>>> db.sadd('userids', diff_set)
[...]
DataError: Invalid input of type: 'set'. Convert to a byte, string or number first.

直接将集合作为参数传递进去是不可以的,所以可以将 “diff 集合” 中的元素一个个取出,然后一个个添加进去。
或者使用以下稍微 pythonic 一点的写法:

>>> db.sadd('userids', *diff_set)
2

>>> 

2.2 有序集合 Z

2.2.1 ZADD
? issue
AttributeError: flot/string/integer object has no attribute 'items' 1
#################################################
#               case 1                          #
#################################################
#### This happened after using redis 3.0.0.post1, 
#### when I uninstalled it and installed 2.10.6, it's working.
## Reference: https://github.com/andymccurdy/redis-py/issues/1068
Traceback (most recent call last):

[...]

File "/myenv/lib/python3.5/site-packages/redis/client.py", line 2263, in zadd
for pair in iteritems(mapping):
File "/myenv/lib/python3.5/site-packages/redis/_compat.py", line 123, in iteritems
return iter(x.items())
AttributeError: 'float' object has no attribute 'items'

#######################################
#                 case 2              #
#######################################
In [17]: rd.zadd("RANK", _id, _rank)                                 
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-17-75a3699246e4> in <module>
----> 1 rd.zadd("RANK", _id, _rank)

~/.virtualenvs/优快云-Data/lib/python3.5/site-packages/redis/client.py in zadd(self, name, mapping, nx, xx, ch, incr)
   2261             pieces.append(Token.get_token('INCR'))
   2262             options['as_score'] = True
-> 2263         for pair in iteritems(mapping):
   2264             pieces.append(pair[1])
   2265             pieces.append(pair[0])

~/.virtualenvs/优快云-Data/lib/python3.5/site-packages/redis/_compat.py in iteritems(x)
    121 
    122     def iteritems(x):
--> 123         return iter(x.items())
    124 
    125     def iterkeys(x):

AttributeError: 'str' object has no attribute 'items'

Solution
#
# this \/ from "https://github.com/andymccurdy/redis-py/issues/1068":
#
import redis
r = redis.Redis(...)

if redis.VERSION[0] < 3:
    r.zadd('my-key', element1=score1)
else:
    r.zadd('my-key', {element1: score1})

#
# fix ## case 2 ## solution for example (a simple way)
#
rd.zadd("RANK", {_id: _rank})
'''
## use:
>>> rd.zadd("<the key>", {member1: score1, member2: score2,
                          member3: score3, }) # , member4: score4, ...
##  could work also.(add multi-members with score)
'''
2.2.2 ZCARD - n/a

2.2.3 ZRANK - n/a

返回的是在 redis key 中的该 member 的索引值(而非分数)

2.2.4 zrangebyscore - n/a

返回分数区间的 members,([WITHSCORE] 决定 member 是否带分数)

b) 其它 redis 库? - N/A



Reference


  1. (redis 3.0.0 and 3.0.0.post1) AttributeError: ‘float’ object has no attribute ‘items’ #1068 ↩︎

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值