From f3fbd0cc1401e1688876cc6193638064e056c0ec Mon Sep 17 00:00:00 2001 From: Brian Sam-Bodden Date: Thu, 1 Aug 2024 20:39:11 -0700 Subject: [PATCH] feature: findAll by Example paginated reports total elements and number of pages --- .../SimpleRedisDocumentRepository.java | 19 ++++++++++++++++-- .../SimpleRedisEnhancedRepository.java | 19 ++++++++++++++++-- .../com/redis/om/spring/util/ObjectUtils.java | 16 +++++++++------ ...pleDocumentRepositoryIntegrationTests.java | 13 +++++++++++- ...ExampleHashRepositoryIntegrationTests.java | 13 +++++++++++- .../redis/om/spring/util/ObjectUtilsTest.java | 20 ++++++++++--------- 6 files changed, 79 insertions(+), 21 deletions(-) diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/repository/support/SimpleRedisDocumentRepository.java b/redis-om-spring/src/main/java/com/redis/om/spring/repository/support/SimpleRedisDocumentRepository.java index 5acd208c..7e910096 100644 --- a/redis-om-spring/src/main/java/com/redis/om/spring/repository/support/SimpleRedisDocumentRepository.java +++ b/redis-om-spring/src/main/java/com/redis/om/spring/repository/support/SimpleRedisDocumentRepository.java @@ -401,12 +401,27 @@ public Iterable findAll(Example example, Sort sort) { @Override public Page findAll(Example example, Pageable pageable) { SearchStream stream = entityStream.of(example.getProbeType()); - var offset = pageable.getOffset() * pageable.getPageSize(); + var offset = pageable.getPageNumber() * pageable.getPageSize(); var limit = pageable.getPageSize(); Slice slice = stream.filter(example).loadAll().limit(limit, Math.toIntExact(offset)) .toList(pageable, stream.getEntityClass()); - return pageFromSlice(slice); + if (indexer.indexDefinitionExistsFor(metadata.getJavaType())) { + String searchIndex = indexer.getIndexName(metadata.getJavaType()); + + SearchOperations searchOps = modulesOperations.opsForSearch(searchIndex); + Query query = new Query(stream.backingQuery()); + query.setNoContent(); + + for (Order order : pageable.getSort()) { + query.setSortBy(order.getProperty(), order.isAscending()); + } + + SearchResult searchResult = searchOps.search(query); + return pageFromSlice(slice, searchResult.getTotalResults(), pageable.getPageSize()); + } else { + return pageFromSlice(slice); + } } /* (non-Javadoc) diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/repository/support/SimpleRedisEnhancedRepository.java b/redis-om-spring/src/main/java/com/redis/om/spring/repository/support/SimpleRedisEnhancedRepository.java index eaec7348..dbcadb76 100644 --- a/redis-om-spring/src/main/java/com/redis/om/spring/repository/support/SimpleRedisEnhancedRepository.java +++ b/redis-om-spring/src/main/java/com/redis/om/spring/repository/support/SimpleRedisEnhancedRepository.java @@ -403,12 +403,27 @@ public Iterable findAll(Example example, Sort sort) { @Override public Page findAll(Example example, Pageable pageable) { SearchStream stream = entityStream.of(example.getProbeType()); - var offset = pageable.getOffset() * pageable.getPageSize(); + var offset = pageable.getPageNumber() * pageable.getPageSize(); var limit = pageable.getPageSize(); Slice slice = stream.filter(example).loadAll().limit(limit, Math.toIntExact(offset)) .toList(pageable, stream.getEntityClass()); - return pageFromSlice(slice); + if (indexer.indexDefinitionExistsFor(metadata.getJavaType())) { + String searchIndex = indexer.getIndexName(metadata.getJavaType()); + + SearchOperations searchOps = modulesOperations.opsForSearch(searchIndex); + Query query = new Query(stream.backingQuery()); + query.setNoContent(); + + for (Order order : pageable.getSort()) { + query.setSortBy(order.getProperty(), order.isAscending()); + } + + SearchResult searchResult = searchOps.search(query); + return pageFromSlice(slice, searchResult.getTotalResults(), pageable.getPageSize()); + } else { + return pageFromSlice(slice); + } } @Override diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/util/ObjectUtils.java b/redis-om-spring/src/main/java/com/redis/om/spring/util/ObjectUtils.java index 70d90fa7..d0493676 100644 --- a/redis-om-spring/src/main/java/com/redis/om/spring/util/ObjectUtils.java +++ b/redis-om-spring/src/main/java/com/redis/om/spring/util/ObjectUtils.java @@ -468,15 +468,19 @@ public static String getKey(String keyspace, Object id) { } public static Page pageFromSlice(Slice slice) { + return pageFromSlice(slice, Long.MAX_VALUE, slice.getPageable().getPageSize()); + } + + public static Page pageFromSlice(Slice slice, long totalElements, int pageSize) { return new Page<>() { @Override public int getTotalPages() { - return -1; + return (totalElements == 0 || pageSize == 0) ? 0 : (int) Math.ceil((double) totalElements / (double) pageSize); } @Override public long getTotalElements() { - return -1; + return totalElements; } @Override @@ -516,22 +520,22 @@ public Sort getSort() { @Override public boolean isFirst() { - return slice.isFirst(); + return getNumber() == 0; } @Override public boolean isLast() { - return slice.isLast(); + return getNumber() + 1 == getTotalPages(); } @Override public boolean hasNext() { - return slice.hasNext(); + return getNumber() + 1 < getTotalPages(); } @Override public boolean hasPrevious() { - return slice.hasPrevious(); + return getNumber() > 0; } @Override diff --git a/redis-om-spring/src/test/java/com/redis/om/spring/repository/support/QueryByExampleDocumentRepositoryIntegrationTests.java b/redis-om-spring/src/test/java/com/redis/om/spring/repository/support/QueryByExampleDocumentRepositoryIntegrationTests.java index a11c00d8..adbb4e1f 100644 --- a/redis-om-spring/src/test/java/com/redis/om/spring/repository/support/QueryByExampleDocumentRepositoryIntegrationTests.java +++ b/redis-om-spring/src/test/java/com/redis/om/spring/repository/support/QueryByExampleDocumentRepositoryIntegrationTests.java @@ -106,8 +106,19 @@ void shouldFindAllPagedByExample() { PersonDoc person = new PersonDoc(); person.setHometown(walt.getHometown()); - Page result = repository.findAll(Example.of(person), PageRequest.of(0, 2)); + Pageable firstPage = PageRequest.of(0, 2); + Page result = repository.findAll(Example.of(person), firstPage); assertThat(result).hasSize(2); + assertThat(result.getTotalElements()).isEqualTo(3); + assertThat(result.getTotalPages()).isEqualTo(2); + assertThat(result.hasNext()).isTrue(); + + Pageable nextPage = result.nextPageable(); + Page next = repository.findAll(Example.of(person), nextPage); + assertThat(next).hasSize(1); + assertThat(next.getTotalElements()).isEqualTo(3); + assertThat(next.getTotalPages()).isEqualTo(2); + assertThat(next.hasNext()).isFalse(); } @Test diff --git a/redis-om-spring/src/test/java/com/redis/om/spring/repository/support/QueryByExampleHashRepositoryIntegrationTests.java b/redis-om-spring/src/test/java/com/redis/om/spring/repository/support/QueryByExampleHashRepositoryIntegrationTests.java index aec19bd6..a764e8ec 100644 --- a/redis-om-spring/src/test/java/com/redis/om/spring/repository/support/QueryByExampleHashRepositoryIntegrationTests.java +++ b/redis-om-spring/src/test/java/com/redis/om/spring/repository/support/QueryByExampleHashRepositoryIntegrationTests.java @@ -110,8 +110,19 @@ void shouldFindAllPagedByExample() { PersonHash person = new PersonHash(); person.setHometown(walt.getHometown()); - Page result = repository.findAll(Example.of(person), PageRequest.of(0, 2)); + Pageable firstPage = PageRequest.of(0, 2); + Page result = repository.findAll(Example.of(person), firstPage); assertThat(result).hasSize(2); + assertThat(result.getTotalElements()).isEqualTo(3); + assertThat(result.getTotalPages()).isEqualTo(2); + assertThat(result.hasNext()).isTrue(); + + Pageable nextPage = result.nextPageable(); + Page next = repository.findAll(Example.of(person), nextPage); + assertThat(next).hasSize(1); + assertThat(next.getTotalElements()).isEqualTo(3); + assertThat(next.getTotalPages()).isEqualTo(2); + assertThat(next.hasNext()).isFalse(); } @Test diff --git a/redis-om-spring/src/test/java/com/redis/om/spring/util/ObjectUtilsTest.java b/redis-om-spring/src/test/java/com/redis/om/spring/util/ObjectUtilsTest.java index a1f99152..16e4c3f6 100644 --- a/redis-om-spring/src/test/java/com/redis/om/spring/util/ObjectUtilsTest.java +++ b/redis-om-spring/src/test/java/com/redis/om/spring/util/ObjectUtilsTest.java @@ -347,25 +347,27 @@ void testFlattenCollection() { @Test void testPageFromSlice() { List strings = List.of("Pantufla", "Mondongo", "Latifundio", "Alcachofa"); - Slice slice = new SliceImpl<>(strings); + List sliceContent = strings.subList(0, 2); + Slice slice = new SliceImpl<>(sliceContent); - Page page = ObjectUtils.pageFromSlice(slice); + Page page = ObjectUtils.pageFromSlice(slice, strings.size(), 2); - assertThat(page.getContent()).hasSize(4); + assertThat(page.getContent()).hasSize(2); assertThat(page.getContent().get(0)).isEqualTo("Pantufla"); assertThat(page.getNumber()).isEqualTo(slice.getNumber()); assertThat(page.getSize()).isEqualTo(slice.getSize()); assertThat(page.getNumberOfElements()).isEqualTo(slice.getNumberOfElements()); assertThat(page.getSort()).isEqualTo(slice.getSort()); assertThat(page.hasContent()).isEqualTo(slice.hasContent()); - assertThat(page.hasNext()).isEqualTo(slice.hasNext()); - assertThat(page.hasPrevious()).isEqualTo(slice.hasPrevious()); - assertThat(page.isFirst()).isEqualTo(slice.isFirst()); - assertThat(page.isLast()).isEqualTo(slice.isLast()); + assertThat(page.hasNext()).isEqualTo(true); + assertThat(page.hasPrevious()).isEqualTo(false); + assertThat(page.isFirst()).isEqualTo(true); + assertThat(page.isLast()).isEqualTo(false); assertThat(page.nextPageable()).isEqualTo(slice.nextPageable()); assertThat(page.previousPageable()).isEqualTo(slice.previousPageable()); - assertThat(page.getTotalPages()).isEqualTo(-1); - assertThat(page.getPageable()).isEqualTo(Pageable.ofSize(4)); + assertThat(page.getTotalPages()).isEqualTo(2); + assertThat(page.getPageable()).isEqualTo(Pageable.ofSize(2)); + assertThat(page.getTotalElements()).isEqualTo(4); } @Test