AWS DynamoDB query top 5 scores for country

Let’s take a look at how to query top 5 scores from AWS DynamoDB, let say we have some top scores table and want to get top 5 performers for the specific country. What we also need is not to waste the network resources, that’s why we will specify what exact fields we need to fetch from server – with help of projectionExpression.
Moreover let’s take a look at how to deal with the following error:
com.amazon.coral.validate#ValidationException”,”message”:”Invalid ProjectionExpression: Attribute name is a reserved keyword; reserved keyword: name”

it could be solved by adding reserved words to the expressionAttributeNames, e.g. instead of

queryExpression.projectionExpression = "userId,challenge,country,name,total"

where name and total are reserved words let’s do the following

queryExpression.expressionAttributeNames = [
            "#n": "name",
            "#t": "total",
        ]
queryExpression.projectionExpression = "userId,challenge,country,#n,#t"

That approach will eliminate the ValidationException – reserved keyword; reserved keyword error.

Here’s the whole method

func getTopScores(successHandler: @escaping (_ results: [BubbleWrapProgress]) -> Void) {
        // Scan implementation.
        let objectMapper = AWSDynamoDBObjectMapper.default()
        let scanExpression = AWSDynamoDBScanExpression()
        scanExpression.limit = 5
        scanExpression.mutableOrderedSetValue(forKey: "total")
        scanExpression.filterExpression = "#total > :total"
        scanExpression.expressionAttributeNames = ["#total": "total" ,]
        scanExpression.expressionAttributeValues = [":total": 1 ,]
 
        scanExpression.indexName = "userId-total"
 
        objectMapper.scan(BubbleWrapProgress.self, expression: scanExpression, completionHandler: {(response: AWSDynamoDBPaginatedOutput?, error: Error?) -> Void in
            DispatchQueue.main.async(execute: {
                if let error = error {
                    print("Amazon DynamoDB Save Error: \(error)")
                    return
                }
                if let response = response {
                    let results = response.items as! [BubbleWrapProgress]
                    successHandler(results)
                }
            })
        })
    }

To make it work we need to create several indexes in dynamodb (mobile hub -> mange application -> edit data base):

That’s pretty much it.

Social Share Toolbar