java—用spring数据中的cassandrarepository实现cassandra分页的正确方法

yws3nbqq  于 2021-06-15  发布在  Cassandra
关注(0)|答案(3)|浏览(907)

我正在寻找一个解决方案,用cassandra(版本 3.11.3 )数据库。我们用的是Spring Boot 2.0.5.RELEASEspring-boot-starter-data-cassandra 作为一种依赖。
作为spring数据的 CassandraRepository<T, ID> 接口不扩展 PagingAndSortingRepository 我们没有像以前那样获得完整的分页功能 JPA .
我阅读了spring数据cassandra文档,可以找到一种可能的方法来实现以cassandra和spring数据为基础的分页 CassandraRepository 接口具有以下可用方法 Slice<T> findAll(Pageable pageable); . 我知道cassandra无法获得特定的页面,并且总是需要page zero来遍历所有页面,正如文档中所记录的那样 CassandraPageRequest :
cassandra特定的{@link pagerequest}实现,提供对{@link pagingstate}的访问。这个类允许创建第一个页面请求,并表示通过cassandra分页是基于获取页面的进度,并且只允许向前导航。访问特定页面需要获取所有页面,直到到达所需页面。
在我的用例中,我们有>1.000.000个数据库条目,并希望在单页应用程序中分页显示它们。
我目前的方法如下:

@RestController
@RequestMapping("/users")
public class UsersResource {

  @Autowired
  UserRepository    userRepository;

  @GetMapping
  public ResponseEntity<List<User>> getAllTests(
            @RequestParam(defaultValue = "0", name = "page") @Positive int requiredPage, 
            @RequestParam(defaultValue = "500", name = "size") int size) {

    Slice<User> resultList = userRepository.findAll(CassandraPageRequest.first(size));

    int currentPage = 0;

    while (resultList.hasNext() && currentPage <= requiredPage) {
      System.out.println("Current Page Number: " + currentPage);
      resultList = userRepository.findAll(resultList.nextPageable());
      currentPage++;
    }

    return ResponseEntity.ok(resultList.getContent());
  }
}

但是使用这种方法,我必须找到请求的页面,同时将所有数据库条目提取到内存中,并进行迭代,直到找到正确的页面。是否有不同的方法来找到正确的页面,或者我必须使用当前的解决方案?
我的cassandra表定义如下所示:

CREATE TABLE user (
  id int, firstname varchar, 
  lastname varchar, 
  code varchar, 
  PRIMARY KEY(id)
);
c9x0cxw0

c9x0cxw01#

请参见下面的代码。可能会有帮助。

@GetMapping("/loadData")
    public Mono<DataTable> loadData(@RequestParam boolean reset, @RequestParam(required = false) String tag, WebSession session) {
        final String sessionId = session.getId();
        IMap<String, String> map = Context.get(HazelcastInstance.class).getMap("companygrouping-pageable-map");
        int pageSize = Context.get(EnvProperties.class).getPageSize();
        Pageable pageRequest;

        if (reset)
            map.remove(sessionId);

        String serializedPagingState = map.compute(sessionId, (k, v) -> (v == null) ? null : map.get(session.getId()));

        pageRequest = StringUtils.isBlank(serializedPagingState) ? CassandraPageRequest.of(0, pageSize)
                : CassandraPageRequest.of(PageRequest.of(0, pageSize), PagingState.fromString(serializedPagingState)).next();

        Mono<Slice<TagMerge>> sliceMono = StringUtils.isNotBlank(tag)
                ? Context.get(TagMergeRepository.class).findByKeyStatusAndKeyTag(Status.NEW, tag, pageRequest)
                : Context.get(TagMergeRepository.class).findByKeyStatus(Status.NEW, pageRequest);

        Flux<TagMerge> flux = sliceMono.map(t -> convert(t, map, sessionId)).flatMapMany(Flux::fromIterable);
        Mono<DataTable> dataTabelMono = createTableFrom(flux).doOnError(e -> log.error("{}", e));
        if (reset) {
            Mono<Long> countMono = Mono.empty();
            if (StringUtils.isNotBlank(tag))
                countMono = Context.get(TagMergeRepository.class).countByKeyStatusAndKeyTag(Status.NEW, tag);
            else
                countMono = Context.get(TagMergeRepository.class).countByKeyStatus(Status.NEW);
            dataTabelMono = dataTabelMono.zipWith(countMono, (t, k) -> {
                t.setTotalRows(k);
                return t;
            });
        }
        return dataTabelMono;
    }

private List<TagMerge> convert(Slice<TagMerge> slice, IMap<String, String> map, String id) {
        PagingState pagingState = ((CassandraPageRequest) slice.getPageable()).getPagingState();
        if (pagingState != null)
            map.put(id, pagingState.toString());
        return slice.getContent();
    }
2fjabf4q

2fjabf4q2#

cassandra支持正向分页,这意味着您可以获取前n行,然后可以获取n+1和2n之间的行,依此类推,直到数据结束,但不能直接获取n+1和2n之间的行。

b09cbbtk

b09cbbtk3#

我所做的是创建一个包含内容和pagingstate散列的page对象。
在初始页面中,我们有简单的分页 Pageable pageRequest = CassandraPageRequest.of(0,5); 一旦找到了我们就得到了切片 Slice<Group> slice = groupRepository.findAll(pageRequest); 使用切片可以获得分页状态 page.setPageHash(getPageHash((CassandraPageRequest) slice.getPageable())); 哪里 private String getPageHash(CassandraPageRequest pageRequest) { return Base64.toBase64String(pageRequest.getPagingState().toBytes()); } 最后返回一个页面对象,其列表内容和pagingstate为pagehash

相关问题