Retain scroll direction across keyset scroll requests.

Closes #4413
This commit is contained in:
Mark Paluch
2023-06-13 10:55:52 +02:00
committed by Christoph Strobl
parent c5674d9264
commit 05c38b819f
3 changed files with 83 additions and 5 deletions

View File

@@ -61,7 +61,8 @@ class ScrollUtils {
Document sortObject = query.getSortObject();
KeysetScrollPosition keyset = query.getKeyset();
KeysetScrollDirector director = KeysetScrollDirector.of(keyset.getDirection());
Direction direction = keyset.getDirection();
KeysetScrollDirector director = KeysetScrollDirector.of(direction);
List<T> resultsToUse = director.postPostProcessResults(result, query.getLimit());
@@ -71,7 +72,7 @@ class ScrollUtils {
Entity<T> entity = operations.forEntity(last);
Map<String, Object> keys = entity.extractKeys(sortObject, sourceType);
return ScrollPosition.forward(keys);
return ScrollPosition.of(keys, direction);
};
return Window.from(resultsToUse, positionFunction, hasMoreElements(result, query.getLimit()));

View File

@@ -190,9 +190,30 @@ class MongoTemplateScrollTests {
window = template.scroll(q.with(window.positionAt(0)).limit(2), Person.class);
assertThat(window).hasSize(2);
assertThat(window).containsOnly(john20, john40_1);
assertThat(window.hasNext()).isTrue();
assertThat(window.isLast()).isFalse();
assertThat(window).containsOnly(jane_20, jane_40);
assertThat(window.hasNext()).isFalse();
assertThat(window.isLast()).isTrue();
}
@Test // GH-4413
void shouldAllowInitialBackwardSort() {
Person jane_20 = new Person("Jane", 20);
Person jane_40 = new Person("Jane", 40);
Person jane_42 = new Person("Jane", 42);
Person john20 = new Person("John", 20);
Person john40_1 = new Person("John", 40);
Person john40_2 = new Person("John", 40);
template.insertAll(Arrays.asList(john20, john40_1, john40_2, jane_20, jane_40, jane_42));
Query q = new Query(where("firstName").regex("J.*")).with(Sort.by("firstName", "age"));
q.with(ScrollPosition.keyset().backward()).limit(3);
Window<Person> window = template.scroll(q, Person.class);
assertThat(window).containsExactly(john20, john40_1, john40_2);
window = template.scroll(q.with(window.positionAt(0)).limit(3), Person.class);
assertThat(window).containsExactly(jane_20, jane_40, jane_42);
}
@ParameterizedTest // GH-4308

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import static org.assertj.core.api.AssertionsForClassTypes.*;
import static org.mockito.Mockito.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.data.domain.KeysetScrollPosition;
import org.springframework.data.domain.ScrollPosition;
import org.springframework.data.domain.Window;
import org.springframework.data.mongodb.core.EntityOperations.Entity;
import org.springframework.data.mongodb.core.query.Query;
/**
* Unit tests for {@link ScrollUtils}.
*
* @author Mark Paluch
*/
class ScrollUtilsUnitTests {
@Test // GH-4413
void positionShouldRetainScrollDirection() {
Query query = new Query();
query.with(ScrollPosition.keyset().backward());
EntityOperations entityOperationsMock = mock(EntityOperations.class);
Entity entityMock = mock(Entity.class);
when(entityOperationsMock.forEntity(any())).thenReturn(entityMock);
when(entityMock.extractKeys(any(), any())).thenReturn(Map.of("k", "v"));
Window<Integer> window = ScrollUtils.createWindow(query, new ArrayList<>(List.of(1, 2, 3)), Integer.class,
entityOperationsMock);
assertThat(window.positionAt(0)).isInstanceOf(KeysetScrollPosition.class);
assertThat(((KeysetScrollPosition) window.positionAt(0)).scrollsBackward()).isTrue();
}
}