|
| 1 | +import os |
| 2 | +import json |
| 3 | +import settings |
| 4 | +from lambda_base import LambdaBase |
| 5 | +from boto3.dynamodb.conditions import Key, Attr |
| 6 | +from jsonschema import validate |
| 7 | +from decimal_encoder import DecimalEncoder |
| 8 | +from parameter_util import ParameterUtil |
| 9 | + |
| 10 | + |
| 11 | +class UsersArticlesPopular(LambdaBase): |
| 12 | + def get_schema(self): |
| 13 | + return { |
| 14 | + 'type': 'object', |
| 15 | + 'properties': { |
| 16 | + 'user_id': settings.parameters['user_id'], |
| 17 | + 'limit': settings.parameters['limit'], |
| 18 | + 'article_id': settings.parameters['article_id'], |
| 19 | + 'popular_sort_key': settings.parameters['popular_sort_key'] |
| 20 | + }, |
| 21 | + 'required': ['user_id'] |
| 22 | + } |
| 23 | + |
| 24 | + def validate_params(self): |
| 25 | + ParameterUtil.cast_parameter_to_int(self.params, self.get_schema()) |
| 26 | + validate(self.params, self.get_schema()) |
| 27 | + |
| 28 | + def exec_main_proc(self): |
| 29 | + article_info_table = self.dynamodb.Table(os.environ['ARTICLE_INFO_TABLE_NAME']) |
| 30 | + limit = UsersArticlesPopular.get_index_limit(self.params) |
| 31 | + |
| 32 | + query_params = { |
| 33 | + 'Limit': limit, |
| 34 | + 'IndexName': 'user_id-popular_sort_key-index', |
| 35 | + 'KeyConditionExpression': Key('user_id').eq(self.params['user_id']), |
| 36 | + 'FilterExpression': Attr('status').eq('public'), |
| 37 | + 'ScanIndexForward': False |
| 38 | + } |
| 39 | + |
| 40 | + if UsersArticlesPopular.require_last_evaluated_key(self.params): |
| 41 | + last_evaluated_key = { |
| 42 | + 'user_id': self.params['user_id'], |
| 43 | + 'article_id': self.params['article_id'], |
| 44 | + 'popular_sort_key': int(self.params['popular_sort_key']) |
| 45 | + } |
| 46 | + |
| 47 | + query_params.update({'ExclusiveStartKey': last_evaluated_key}) |
| 48 | + |
| 49 | + response = article_info_table.query(**query_params) |
| 50 | + |
| 51 | + items = response['Items'] |
| 52 | + |
| 53 | + while 'LastEvaluatedKey' in response and len(response['Items']) < limit: |
| 54 | + query_params.update({'ExclusiveStartKey': response['LastEvaluatedKey']}) |
| 55 | + response = article_info_table.query(**query_params) |
| 56 | + items.extend(response['Items']) |
| 57 | + |
| 58 | + if len(items) >= limit: |
| 59 | + last_evaluated_key = { |
| 60 | + 'user_id': self.params['user_id'], |
| 61 | + 'article_id': items[limit - 1]['article_id'], |
| 62 | + 'popular_sort_key': int(items[limit - 1]['popular_sort_key']) |
| 63 | + } |
| 64 | + response.update({'LastEvaluatedKey': last_evaluated_key}) |
| 65 | + break |
| 66 | + |
| 67 | + response['Items'] = items[:limit] |
| 68 | + |
| 69 | + return { |
| 70 | + 'statusCode': 200, |
| 71 | + 'body': json.dumps(response, cls=DecimalEncoder) |
| 72 | + } |
| 73 | + |
| 74 | + @staticmethod |
| 75 | + def get_index_limit(params): |
| 76 | + if params is not None and params.get('limit') is not None: |
| 77 | + return int(params.get('limit')) |
| 78 | + else: |
| 79 | + return settings.USERS_ARTICLE_POPULAR_INDEX_DEFAULT_LIMIT |
| 80 | + |
| 81 | + @staticmethod |
| 82 | + def require_last_evaluated_key(params): |
| 83 | + if params.get('article_id') is not None and params.get('popular_sort_key') is not None: |
| 84 | + return True |
| 85 | + return False |
0 commit comments