我正在尝试为我的应用程序实现某种分页功能,该功能在后端使用cassandra。
CREATE TABLE sample (
some_pk int,
some_id int,
name1 txt,
name2 text,
value text,
PRIMARY KEY (some_pk, some_id, name1, name2)
)
WITH CLUSTERING ORDER BY(some_id DESC)
我想查询100条记录,然后将最后一条记录键存储在内存中,以备后用。
+---------+---------+-------+-------+-------+
| sample_pk| some_id | name1 | name2 | value |
+---------+---------+-------+-------+-------+
| 1 | 125 | x | '' | '' |
+---------+---------+-------+-------+-------+
| 1 | 124 | a | '' | '' |
+---------+---------+-------+-------+-------+
| 1 | 124 | b | '' | '' |
+---------+---------+-------+-------+-------+
| 1 | 123 | y | '' | '' |
+---------+---------+-------+-------+-------+
(为简单起见,我将一些列留空。分区键(sample_pk)并不重要)
假设我的页面大小为2。
select * from sample where sample_pk=1 limit 2;
返回前2行。现在我将最后一条记录存储在查询结果中,然后再次运行查询以获取下2行;
这是由于单个非EQ关系的限制而无法使用的查询
select * from where sample_pk=1 and some_id <= 124 and name1>='a' and name2>='' limit 2;
此结果返回错误的结果,因为some_id按降序排列,而name列按升序排列。
select * from where sample_pk=1 and (some_id, name1, name2) <= (124, 'a', '') limit 2;
所以我被困住了。如何实现分页?
答案 0 :(得分:2)
您可以运行第二个查询,例如
.vcproj
现在,在提取记录之后,请忽略已读取的记录(之所以可以这样做,是因为您要存储上一个选择查询中的最后一条记录)。
如果忽略这些记录,如果您最终得到的行/记录为空列表,则意味着您已遍历所有记录,否则将继续执行此分页任务。
答案 1 :(得分:1)
您不必在内存中存储任何密钥,也不需要在cqlsh查询中使用limit
。只需在应用程序代码中使用datastax driver的功能来进行分页,就像下面的代码一样:
public Response getFromCassandra(Integer itemsPerPage, String pageIndex) {
Response response = new Response();
String query = "select * from sample where sample_pk=1";
Statement statement = new SimpleStatement(query).setFetchSize(itemsPerPage); // set the number of items we want per page (fetch size)
// imagine page '0' indicates the first page, so if pageIndex = '0' then there is no paging state
if (!pageIndex.equals("0")) {
statement.setPagingState(PagingState.fromString(pageIndex));
}
ResultSet rows = session.execute(statement); // execute the query
Integer numberOfRows = rows.getAvailableWithoutFetching(); // this should get only number of rows = fetchSize (itemsPerPage)
Iterator<Row> iterator = rows.iterator();
while (numberOfRows-- != 0) {
response.getRows.add(iterator.next());
}
PagingState pagingState = rows.getExecutionInfo().getPagingState();
if(pagingState != null) { // there is still remaining pages
response.setNextPageIndex(pagingState.toString());
}
return response;
}
请注意,如果您使while循环如下所示:
while(iterator.hasNext()) {
response.getRows.add(iterator.next());
}
它将首先获取与我们设置的获取大小相等的行数,然后,只要查询仍与Cassandra中的某些行匹配,它将再次从cassandra中获取,直到从cassandra中获取与查询匹配的所有行,这可能如果要实现分页功能,则不适用
来源:https://docs.datastax.com/en/developer/java-driver/3.2/manual/paging/