Skip to content

Commit

Permalink
Adding ability to get many hashed key values
Browse files Browse the repository at this point in the history
  • Loading branch information
tim.reichard committed Feb 18, 2021
1 parent e716d8b commit 82c3883
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 7 deletions.
6 changes: 6 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ History
=======


v0.11.2 (2021-02-18)
-----------------------

* Add custom hmget_many & hmgetall_many redis commands to get many hashed keys data.


v0.11.1 (2021-02-18)
-----------------------

Expand Down
75 changes: 69 additions & 6 deletions aioradio/redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ async def hmget(self, key: str, fields: List[str], use_json: bool=None, encoding
Args:
key (str): cache key
fields (str): hash field
fields (List[str]): hash fields
use_json (bool, optional): convert json values to objects. Defaults to None.
Returns:
Expand All @@ -193,6 +193,38 @@ async def hmget(self, key: str, fields: List[str], use_json: bool=None, encoding

return items

async def hmget_many(self, keys: List[str], fields: List[str], use_json: bool=None, encoding: Union[str, None]='utf-8') -> List[Any]:
"""Get the values of all the given fields for many hashed keys.
Args:
keys (List[str]): cache keys
fields (List[str]): hash fields
use_json (bool, optional): convert json values to objects. Defaults to None.
encoding (Union[str, None]): encoding of values
Returns:
List[Any]: any
"""

if use_json is None:
use_json = self.use_json

transaction = self.pool.multi_exec()
for key in keys:
transaction.hmget(key, *fields, encoding=encoding)

results = []
for values in await transaction.execute():
items = {}
for index, value in enumerate(values):
if value is not None:
if use_json:
value = orjson.loads(value)
items[fields[index]] = value
results.append(items)

return results

async def hgetall(self, key: str, use_json: bool=None, encoding: Union[str, None]='utf-8') -> Any:
"""Get all the fields and values in a hash.
Expand All @@ -208,14 +240,45 @@ async def hgetall(self, key: str, use_json: bool=None, encoding: Union[str, None
use_json = self.use_json

items = {}
results = await self.pool.hgetall(key, encoding=encoding)
for hash_key, value in results.items():
if value is not None and use_json:
value = orjson.loads(value)
items[hash_key] = value
for hash_key, value in (await self.pool.hgetall(key, encoding=encoding)).items():
if value is not None:
if use_json:
value = orjson.loads(value)
items[hash_key] = value

return items

async def hgetall_many(self, keys: List[str], use_json: bool=None, encoding: Union[str, None]='utf-8') -> List[Any]:
"""Get all the fields and values in a hash.
Args:
keys (str): cache keys
use_json (bool, optional): convert json values to objects. Defaults to None.
encoding (Union[str, None]): encoding of values
Returns:
List[Any]: any
"""

if use_json is None:
use_json = self.use_json

transaction = self.pool.multi_exec()
for key in keys:
transaction.hgetall(key, encoding=encoding)

results = []
for item in await transaction.execute():
items = {}
for key, value in item.items():
if value is not None:
if use_json:
value = orjson.loads(value)
items[key] = value
results.append(items)

return results

async def hset(self, key: str, field: str, value: str, use_json: bool=None, expire: int=None) -> int:
"""Set the string value of a hash field.
Expand Down
11 changes: 11 additions & 0 deletions aioradio/tests/redis_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ async def test_hash_redis_functions(cache):
result = await cache.hgetall(key='address_hash', use_json=False)
assert result == items

await cache.hmset(key='tim', items={'firstname': 'Tim', 'lastname': 'Reichard', 'avg': '190'}, expire=1, use_json=False)
await cache.hmset(key='don', items={'firstname': 'Don', 'lastname': 'Mattingly', 'avg': '325'}, expire=1, use_json=False)
result = await cache.hmget_many(keys=['tim', 'don', 'fake'], fields=['firstname', 'lastname'], use_json=False)
assert len(result) == 3
assert result[-1] == {}

result = await cache.hgetall_many(keys=['tim', 'don', 'fake'], use_json=False)
assert len(result) == 3
assert result[0]['avg'] == '190'
assert result[-1] == {}


async def test_set_one_item(payload, cache):
"""Test set_one_item."""
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
long_description = fileobj.read()

setup(name='aioradio',
version='0.11.1',
version='0.11.2',
description='Generic asynchronous i/o python utilities for AWS services (SQS, S3, DynamoDB, Secrets Manager), Redis, MSSQL (pyodbc), JIRA and more',
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down

0 comments on commit 82c3883

Please sign in to comment.