限制条件
不同于传统关系型数据库支持的翻页查询,在NoSQL的数据模型和API上,实现分页功能有以下限制:
/**
* 范围查询指定范围内的数据,返回指定页数大小的数据,并能根据offset跳过部分行。
*/
private static Pair<List<Row>, RowPrimaryKey> readByPage(OTSClient client, String tableName,
RowPrimaryKey startKey, RowPrimaryKey endKey, int offset, int pageSize) {
Preconditions.checkArgument(offset >= 0, "Offset should not be negative.");
Preconditions.checkArgument(pageSize > 0, "Page size should be greater than 0.");
List<Row> rows = new ArrayList<Row>(pageSize);
int limit = pageSize;
int skip = offset;
RowPrimaryKey nextStart = startKey;
// 若查询的数据量很大,则一次请求有可能不会返回所有的数据,需要流式查询所有需要的数据。
while (limit > 0 && nextStart != null) {
// 构造GetRange的查询参数。
// 注意:startPrimaryKey需要设置为上一次读到的位点,从上一次未读完的地方继续往下读,实现流式的范围查询。
RangeRowQueryCriteria criteria = new RangeRowQueryCriteria(tableName);
criteria.setInclusiveStartPrimaryKey(nextStart);
criteria.setExclusiveEndPrimaryKey(endKey);
// 需要设置正确的limit,这里期望读出的数据行数最多为完整的一页数据以及需要过滤(offset)的数据
criteria.setLimit(skip + limit);
GetRangeRequest request = new GetRangeRequest();
request.setRangeRowQueryCriteria(criteria);
GetRangeResult response = client.getRange(request);
for (Row row : response.getRows()) {
if (skip > 0) {
skip--; // 对于offset之前的数据,需要过滤掉,采用的策略是读出来后在客户端进行过滤。
} else {
rows.add(row);
limit--;
}
}
// 设置下一次查询的起始位点
nextStart = response.getNextStartPrimaryKey();
}
return new Pair<List<Row>, RowPrimaryKey>(rows, nextStart);
}
private static void readByPage(OTSClient client, String tableName) {
int pageSize = 8;
int offset = 33;
RowPrimaryKey startKey = new RowPrimaryKey();
startKey.addPrimaryKeyColumn(COLUMN_GID_NAME, PrimaryKeyValue.INF_MIN);
startKey.addPrimaryKeyColumn(COLUMN_UID_NAME, PrimaryKeyValue.INF_MIN);
RowPrimaryKey endKey = new RowPrimaryKey();
endKey.addPrimaryKeyColumn(COLUMN_GID_NAME, PrimaryKeyValue.INF_MAX);
endKey.addPrimaryKeyColumn(COLUMN_UID_NAME, PrimaryKeyValue.INF_MAX);
// 读第一页,从范围的offset=33的行开始读起
Pair<List<Row>, RowPrimaryKey> result = readByPage(client, tableName, startKey, endKey, offset, pageSize);
for (Row row : result.getKey()) {
System.out.println(row.getColumns());
}
System.out.println("Total rows count: " + result.getKey().size());
// 顺序翻页,读完范围内的所有数据
startKey = result.getValue();
while (startKey != null) {
System.out.println("============= start read next page ==============");
result = readByPage(client, tableName, startKey, endKey, 0, pageSize);
for (Row row : result.getKey()) {
System.out.println(row.getColumns());
}
startKey = result.getValue();
System.out.println("Total rows count: " + result.getKey().size());
}
}
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。