Skip to content

Commit 5d1bd93

Browse files
Add dynamodb utility functions from DSS. (#67)
* Add dynamodb utility functions from DSS. * Python3.5 has no f-strings. >.<
1 parent 5704ea9 commit 5d1bd93

1 file changed

Lines changed: 140 additions & 0 deletions

File tree

dcplib/aws/dynamodb.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
from typing import Generator, Optional
2+
3+
from dss.util.aws.clients import dynamodb as db # type: ignore
4+
5+
6+
class DynamoDBItemNotFound(Exception):
7+
pass
8+
9+
10+
def _format_item(hash_key: str, sort_key: Optional[str], value: Optional[str], ttl: Optional[int] = None) -> dict:
11+
item = {'hash_key': {'S': hash_key}}
12+
if value:
13+
item['body'] = {'S': value}
14+
if sort_key:
15+
item['sort_key'] = {'S': sort_key}
16+
if ttl:
17+
item['ttl'] = {'N': str(ttl)}
18+
return item
19+
20+
21+
def put_item(*, table: str, hash_key: str, sort_key: Optional[str] = None, value: str,
22+
dont_overwrite: Optional[str] = None, ttl: Optional[int] = None):
23+
"""
24+
Put an item into a dynamoDB table.
25+
26+
Will determine the type of db this is being called on by the number of keys provided (omit
27+
sort_key to PUT into a db with only 1 primary key).
28+
29+
:param str table: Name of the table in AWS.
30+
:param str value: Value stored by the two primary keys.
31+
:param str hash_key: 1st primary key that can be used to fetch associated sort_keys and values.
32+
:param str sort_key: 2nd primary key, used with hash_key to fetch a specific value.
33+
Note: If not specified, this will PUT only 1 key (hash_key) and 1 value.
34+
:param str dont_overwrite: Don't overwrite if this parameter exists. For example, setting this
35+
to 'sort_key' won't overwrite if that sort_key already exists in the table.
36+
:param int ttl: Time to Live for the item. Only works if enabled for that specific table.
37+
:return: None
38+
"""
39+
query = {'TableName': table,
40+
'Item': _format_item(hash_key=hash_key, sort_key=sort_key, value=value, ttl=ttl)}
41+
if dont_overwrite:
42+
query['ConditionExpression'] = 'attribute_not_exists({dont_overwrite})'.format(dont_overwrite=dont_overwrite)
43+
db.put_item(**query)
44+
45+
46+
def get_item(*, table: str, hash_key: str, sort_key: Optional[str] = None, return_key: str = 'body') -> str:
47+
"""
48+
Get associated value for a given set of keys from a dynamoDB table.
49+
50+
Will determine the type of db this is being called on by the number of keys provided (omit
51+
sort_key to GET a value from a db with only 1 primary key).
52+
53+
:param str table: Name of the table in AWS.
54+
:param str hash_key: 1st primary key that can be used to fetch associated sort_keys and values.
55+
:param str sort_key: 2nd primary key, used with hash_key to fetch a specific value.
56+
Note: If not specified, this will GET only 1 key (hash_key) and 1 value.
57+
:param str return_key: Either "body" (to return all values) or "sort_key" (to return all 2nd primary keys).
58+
:return: None or str
59+
"""
60+
query = {'TableName': table,
61+
'Key': _format_item(hash_key=hash_key, sort_key=sort_key, value=None)}
62+
item = db.get_item(**query).get('Item')
63+
if item is None:
64+
raise DynamoDBItemNotFound('Query failed to fetch item from database: {query}'.format(query=query))
65+
return item[return_key]['S']
66+
67+
68+
def get_primary_key_items(*, table: str, key: str, return_key: str = 'body') -> Generator[str, None, None]:
69+
"""
70+
Get associated value for a given set of keys from a dynamoDB table.
71+
72+
:param str table: Name of the table in AWS.
73+
:param str key: 1st primary key that can be used to fetch associated sort_keys and values.
74+
:param str return_key: Either "body" (to return all values) or "sort_key" (to return all 2nd primary keys).
75+
:return: Iterable (str)
76+
"""
77+
paginator = db.get_paginator('query')
78+
for db_resp in paginator.paginate(TableName=table,
79+
ScanIndexForward=False, # True = ascending, False = descending
80+
KeyConditionExpression="#hash_key=:key",
81+
ExpressionAttributeNames={'#hash_key': "hash_key"},
82+
ExpressionAttributeValues={':key': {'S': key}}):
83+
for item in db_resp.get('Items', []):
84+
yield item[return_key]['S']
85+
86+
87+
def get_primary_key_count(*, table: str, key: str) -> int:
88+
"""
89+
Returns the number of values associated with a primary key from a dynamoDB table.
90+
91+
:param str table: Name of the table in AWS.
92+
:param str key: 1st primary key that can be used to fetch associated sort_keys and values.
93+
:return: Int
94+
"""
95+
res = db.query(TableName=table,
96+
KeyConditionExpression="#hash_key=:key",
97+
ExpressionAttributeNames={'#hash_key': "hash_key"},
98+
ExpressionAttributeValues={':key': {'S': key}},
99+
Select='COUNT')
100+
return res['Count']
101+
102+
103+
def get_all_table_items(*, table: str, both_keys: bool = False):
104+
"""
105+
Return all items from a dynamoDB table.
106+
107+
:param str table: Name of the table in AWS.
108+
:param str return_key: Either "body" (to return all values) or "sort_key" (to return all 2nd primary keys).
109+
:return: Iterable (str)
110+
"""
111+
paginator = db.get_paginator('scan')
112+
for db_resp in paginator.paginate(TableName=table):
113+
for item in db_resp.get('Items', []):
114+
if both_keys:
115+
yield item['hash_key']['S'], item['sort_key']['S']
116+
else:
117+
yield item['body']['S']
118+
119+
120+
def delete_item(*, table: str, hash_key: str, sort_key: Optional[str] = None):
121+
"""
122+
Delete an item from a dynamoDB table.
123+
124+
Will determine the type of db this is being called on by the number of keys provided (omit
125+
sort_key to DELETE from a db with only 1 primary key).
126+
127+
NOTE:
128+
Unless you specify conditions, DeleteItem is an idempotent operation; running it multiple times
129+
on the same item or attribute does not result in an error response:
130+
https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteItem.html
131+
132+
:param str table: Name of the table in AWS.
133+
:param str hash_key: 1st primary key that can be used to fetch associated sort_keys and values.
134+
:param str sort_key: 2nd primary key, used with hash_key to fetch a specific value.
135+
Note: If not specified, this will DELETE only 1 key (hash_key) and 1 value.
136+
:return: None
137+
"""
138+
query = {'TableName': table,
139+
'Key': _format_item(hash_key=hash_key, sort_key=sort_key, value=None)}
140+
db.delete_item(**query)

0 commit comments

Comments
 (0)