0

对于 Web 应用程序,我想实现一个分页表。DynamoDB“布局”是一个用户有多个项目,因此我选择了partition key=usersort key=created(时间戳)。UI 应在页面中显示项目,总共有 100 个项目中的 50 个项目。

这些项目通过 REST-Api 调用传递给 UI。我只想queryscan一页项目,而不是整个表。分页应该可以向前和向后。

到目前为止,我已经想出了以下内容,使用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();
    }
}

previous 的代码类似,只是它使用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));
    }
}

我想知道我是否正在用这种方法重新发明轮子。

是否可以通过 REST 将 DynamoDBPaginatedQueryListPaginatedScanListUI 传递给 UI,这样如果 javascript 分页访问这些项目,那么它们就会被延迟加载。与其他数据库一起工作时,我从未传输过数据库条目对象,这就是我的代码片段重新打包数据的原因 ( item2dto)。

此外,DynamoDB 的分页看起来有点奇怪:到目前为止,我还没有看到向 UI 提供项目总数的可能性。所以用户界面只有“下一页”和“上一页”的按钮,实际上并不知道接下来会有多少页。因此无法直接跳转到第 5 页。

4

1 回答 1

0

AWS 控制台不会一次加载您的所有数据以节省读取容量。当您获得扫描/查询页面时,您只会获得有关如何获得下一页的信息,这就是为什么控制台无法预先显示它可以显示多少页数据的原因。根据您的架构,您可能能够在应用程序中支持随机页面访问。这是通过先验决定页面的大小以及在分区键中对页码等内容进行第二次编码来完成的。有关详细信息,请参阅此 AWS 论坛帖子

于 2017-02-05T00:35:39.317 回答