PaginatedList DynamoDB через REST

Для веб-приложения я хочу реализовать разбитую на страницы таблицу. "Макет" DynamoDB заключается в том, что для пользователя существует несколько элементов, поэтому я выбрал partition key=user и sort key=created (Метка времени). Пользовательский интерфейс должен представить элементы на страницах по 50 пунктов из общего количества нескольких 100 элементов.

Элементы передаются в пользовательский интерфейс через вызовы REST-Api. Я только хочу query или же scan страница предметов, а не вся таблица. Пагинация должна быть возможна вперед и назад.

До сих пор я придумал следующее, используя DynamoDBMapper:

/**
 * Returns the next page of items DEPENDENT OF THE USER. Note: This method internally uses
 * DynamoDB QUERY. Thus it requires "user" as a parameter. The "created" parameter is optional.
 * If provided, both parameters form the startKey for the pagination.
 * 
 * @param user - mandatory: The user for which to get the next page
 * @param created - optional: for providing a starting point
 * @param limit - the returned page will contain (up to) this number of items
 * @return
 */
public List<SampleItem> getNextPageForUser(final String user, final Long created, final int limit) {
    // To iterate DEPENDENT on the user we use QUERY. The DynamoDB QUERY operation
    // always require the partition key (=user).
    final SampleItem hashKeyObject = new SampleItem();
    hashKeyObject.setUser(user);

    // The created is optional. If provided, it references the starting point
    if (created == null) {
        final DynamoDBQueryExpression<SampleItem> pageExpression = new DynamoDBQueryExpression<SampleItem>()//
                .withHashKeyValues(hashKeyObject)//
                .withScanIndexForward(true) //
                .withLimit(limit);
        return mapper.queryPage(SampleItem.class, pageExpression).getResults();
    } else {
        final Map<String, AttributeValue> startKey = new HashMap<String, AttributeValue>();
        startKey.put(SampleItem.USER, new AttributeValue().withS(user));
        startKey.put(SampleItem.CREATED, new AttributeValue().withN(created.toString()));

        final DynamoDBQueryExpression<SampleItem> pageExpression = new DynamoDBQueryExpression<SampleItem>()//
                .withHashKeyValues(hashKeyObject)//
                .withExclusiveStartKey(startKey)//
                .withScanIndexForward(true) //
                .withLimit(limit);
        return mapper.queryPage(SampleItem.class, pageExpression).getResults();
    }
}

Код для предыдущего похож, только то, что он использует withScanIndexForward(false),

В моем контроллере REST-Api я предлагаю единственный метод:

@RequestMapping(value = "/page/{user}/{created}", method = RequestMethod.GET)
public List<SampleDTO> listQueriesForUserWithPagination(//
        @RequestParam(required = true) final String user,//
        @RequestParam(required = true) final Long created,//
        @RequestParam(required = false) final Integer n,//
        @RequestParam(required = false) final Boolean isBackward//
) {
    final int nrOfItems = n == null ? 100 : n;
    if (isBackward != null && isBackward.booleanValue()) {
        return item2dto(myRepo.getPrevQueriesForUser(user, created, nrOfItems));
    } else {
        return item2dto(myRepo.getNextQueriesForUser(user, created, nrOfItems));
    }
}

Интересно, заново ли я изобретаю колесо с таким подходом?

Будет ли возможно передать DynamoDB PaginatedQueryList или же PaginatedScanList в пользовательский интерфейс через REST, так что, если разбиение на страницы javascript обращается к элементам, то они загружаются лениво. Работая с другими БД, я никогда не переносил объекты записей БД, поэтому мой фрагмент кода переупаковывает данные (item2dto).

Кроме того, нумерация страниц с DynamoDB выглядит немного странно: до сих пор я не видел возможности предоставить интерфейсу пользователя общее количество элементов. Таким образом, пользовательский интерфейс имеет только кнопки для "следующей страницы" и "предыдущей страницы", фактически не зная, сколько страниц последует. Поэтому прямой переход на страницу 5 невозможен.

1 ответ

Консоль AWS не загружает все ваши данные сразу, чтобы сохранить емкость чтения. Когда вы получаете страницу сканирования / запроса, вы получаете только информацию о том, как получить следующую страницу, поэтому консоль не может показать вам, сколько страниц данных она может показать. В зависимости от вашей схемы, вы можете поддерживать произвольный доступ к страницам в вашем приложении. Это делается путем априорного определения размера страниц и второго кодирования, например, номера страницы в ключе раздела. Пожалуйста, см. Этот пост на форуме AWS для деталей.

Другие вопросы по тегам