如何使用键实现cassandra分页?

ru9i0ody  于 2021-06-15  发布在  Cassandra
关注(0)|答案(2)|浏览(578)

我正在尝试为我的应用程序实现某种分页功能,在后端使用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     | ''    | ''    |
+---------+---------+-------+-------+-------+

(为简单起见,我将一些列留空。分区密钥(示例\u pk)不重要)
假设我的页面大小是2。

select * from sample where sample_pk=1 limit 2;

返回前2行。现在我将最后一条记录存储在查询结果中,然后再次运行查询以获得下两行;
这是由于单个非eq关系的限制而无法工作的查询

select * from where sample_pk=1 and some_id <= 124 and name1>='a' and name2>='' limit 2;

这一个返回错误的结果,因为某些\u id按降序排列,而name列按升序排列。

select * from where sample_pk=1 and (some_id, name1, name2) <= (124, 'a', '') limit 2;

所以我被困住了。如何实现分页?

xn1cxnb4

xn1cxnb41#

你可以运行第二个查询,比如,

select * from sample where some_pk =1 and some_id <= 124 limit x;

现在,在获取记录之后,忽略已经读取的记录(可以这样做,因为您存储的是上一个select查询中的最后一条记录)。
在忽略这些记录之后,如果您的行/记录列表为空,则意味着您已经遍历了所有记录,否则请继续执行分页任务。

ikfrs5lh

ikfrs5lh2#

你不需要在内存中存储任何密钥,也不需要使用 limit 在您的cqlsh查询中。只需在应用程序代码中使用datastax驱动程序的功能进行分页,如以下代码所示:

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/

相关问题