Search code examples
javaspringamazon-web-servicesamazon-dynamodbdynamodb-queries

Get last value in DynamoDB Partition


I want to get only the last value in the DDB partition sorted by the sort key of course.

My Table minified looks as follows:

===============================

studentNr | punchTime | classId | locationName

===============================

Partition Key = StudentNr

SortyKey = PunchTime

I am using the AWS Enhanced client for java and I got this query that is working, but the problem is I am getting throttled, (not very high capacity provisioned but still should not get throttled for just this query).

The code looks as follows:

    @Override
    public AttendanceTracking findFirstByStudentNrOrderByPunchTimeDesc(String studentNr) {
        DynamoDbTable<AttendanceTracking> attendanceTable = getTable();
        //Only get last db entry sorted by punchTime
        String today = LocalDateTime.now().toString();
        Key fromKey = Key.builder().partitionValue(studentNr).sortValue(today).build();
        QueryConditional queryConditional = QueryConditional
                .sortLessThan(fromKey);
        Iterable<Page<AttendanceTracking>> results =
                attendanceTable.query(QueryEnhancedRequest.builder()
                        .queryConditional(queryConditional)
                        .scanIndexForward(false)
                        .limit(1)
                        .build());
        List<AttendanceTracking> entries = new ArrayList<>();
        results.forEach(page -> entries.addAll(page.items()));
        if (entries.size() > 0) {
            return entries.get(0);
        }
        return null;
    }

Also, this query takes 6 seconds avg to execute? Yet there should only be a few 100 entries in this specific parition. Not sure if this is because of throttling and the client has automatic retries build in I dont know.

I am thinking its because I do a sortLess than, but I can't imagine it should scan all values in the partition?

Please help


Solution

  • Someone in the comments pointed out the answer. You dont need to have the SortKey involved in this case. Simply search by Partition key and reverse scanIndex limmitting to 1, because DDB already sorts your data is should be in correct order. It also cut the query time down from 6 seconds to 60ms.

      @Override
        public AttendanceTracking findFirstByStudentNrOrderByPunchTimeDesc(String studentNr) {
            DynamoDbTable<AttendanceTracking> attendanceTable = getTable();
            //Only get last db entry sorted by punchTime
            String today = LocalDateTime.now().toString();
            QueryConditional queryConditional = QueryConditional
                .keyEqualTo(Key.builder().partitionValue(studentNr).build());
            Iterable<Page<AttendanceTracking>> results =
                    attendanceTable.query(QueryEnhancedRequest.builder()
                            .queryConditional(queryConditional)
                            .scanIndexForward(false)
                            .limit(1)
                            .build());
            List<AttendanceTracking> entries = new ArrayList<>();
            results.forEach(page -> entries.addAll(page.items()));
            if (entries.size() > 0) {
                return entries.get(0);
            }
            return null;
        }