Skip to content

Commit adbbd33

Browse files
committed
paginated scans for ddb
1 parent 2ba2181 commit adbbd33

1 file changed

Lines changed: 42 additions & 11 deletions

File tree

core/api/db_interface.py

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from botocore.exceptions import ClientError
1313
from copy import copy
1414

15-
1615
from marshmallow import ValidationError
1716

1817
from .. import dynamo_db
@@ -22,32 +21,64 @@
2221
fishfry_table = dynamo_db.tables['FishFryDB']
2322
fishfry_stats = dynamo_db.tables['FishFryStats']
2423

24+
class DecimalEncoder(json.JSONEncoder):
25+
"""use to convert any DynamoDB items stored as Decimal objects to numbers.
26+
"""
27+
28+
def default(self, o):
29+
if isinstance(o, decimal.Decimal):
30+
return float(o)
31+
return super(DecimalEncoder, self).default(o)
2532

2633
def decimal_decoder(json_obj):
2734
"""convert any floats in a dictionary (loaded from a json) to Decimal type.
2835
This is required in order to load data to DynamoDB.
2936
"""
3037
return json.loads(json.dumps(json_obj), parse_float=decimal.Decimal)
3138

39+
def decimal_encoder(json_obj):
40+
return json.loads(json.dumps(json_obj, cls=DecimalEncoder))
3241

33-
class DecimalEncoder(json.JSONEncoder):
34-
"""use to convert any DynamoDB items stored as Decimal objects to numbers.
42+
43+
def _paginated_scan(ddb_table):
44+
"""performs a paginated scan of the DynamoDB table
3545
"""
46+
47+
response = ddb_table.scan()
48+
data = response['Items']
49+
print(len(data))
3650

37-
def default(self, o):
38-
if isinstance(o, decimal.Decimal):
39-
return float(o)
40-
return super(DecimalEncoder, self).default(o)
51+
while response.get('LastEvaluatedKey'):
52+
response = ddb_table.scan(ExclusiveStartKey=response['LastEvaluatedKey'])
53+
addl_data = response['Items']
54+
print(len(addl_data))
55+
data.extend(addl_data)
56+
57+
return {'Items': data, 'Count': len(data)}
58+
59+
def retrieve_all_records(ddb_table):
60+
""" query the DB and decode
61+
"""
62+
63+
return json.loads(
64+
json.dumps(
65+
_paginated_scan(ddb_table),
66+
cls=DecimalEncoder
67+
)
68+
)
4169

70+
def is_not_blank(s):
71+
return bool(s and s.strip())
4272

4373
def replace_emptry_strings(a_dict):
4474
"""use to convert empty strings to None values; DynamoDB doesn't like
4575
empty strings
4676
"""
4777
for k, v in a_dict.items():
4878
if not isinstance(v, dict):
49-
if v == "":
50-
a_dict[k] = None
79+
if isinstance(v, str):
80+
if not is_not_blank(v):
81+
a_dict[k] = None
5182
else:
5283
replace_emptry_strings(v)
5384

@@ -62,11 +93,11 @@ def get_all_fishfries(published=None, validated=None, has_geom=True):
6293
:type validated: bool, optional
6394
:param has_geom: [description], defaults to True
6495
:type has_geom: bool, optional
65-
96+
6697
"""
6798

6899
# this effectively returns the "features" array of a GeoJSON Feature Collection
69-
response = fishfry_table.scan()
100+
response = retrieve_all_records(fishfry_table)
70101
if response['Count'] > 0:
71102
# list of features
72103
features = response["Items"]

0 commit comments

Comments
 (0)