@@ -39,11 +39,13 @@ import com.querydsl.core.types.PathType;
|
||||
import com.querydsl.core.types.SubQueryExpression;
|
||||
import com.querydsl.core.types.TemplateExpression;
|
||||
import com.querydsl.core.types.Visitor;
|
||||
import com.querydsl.core.types.Order;
|
||||
|
||||
/**
|
||||
* Serializes the given Querydsl query to a Document query for Couchbase.
|
||||
*
|
||||
* @author Michael Reiche
|
||||
* @author Tigran Babloyan
|
||||
*/
|
||||
public abstract class CouchbaseDocumentSerializer implements Visitor<Object, Void> {
|
||||
|
||||
@@ -55,8 +57,15 @@ public abstract class CouchbaseDocumentSerializer implements Visitor<Object, Voi
|
||||
Sort sort = Sort.unsorted();
|
||||
for (OrderSpecifier<?> orderBy : orderBys) {
|
||||
Object key = orderBy.getTarget().accept(this, null);
|
||||
// sort.and(Sort.by(orderBy));
|
||||
// sort.append(key.toString(), orderBy.getOrder() == Order.ASC ? 1 : -1);
|
||||
String keyAsString = key.toString();
|
||||
Sort.NullHandling sortNullHandling = switch (orderBy.getNullHandling()) {
|
||||
case NullsFirst -> Sort.NullHandling.NULLS_FIRST;
|
||||
case NullsLast -> Sort.NullHandling.NULLS_LAST;
|
||||
default -> Sort.NullHandling.NATIVE;
|
||||
};
|
||||
Sort.Direction sortDirection = orderBy.getOrder() == Order.ASC ? Sort.Direction.ASC : Sort.Direction.DESC;
|
||||
Sort.Order sortOrder = new Sort.Order(sortDirection, keyAsString, sortNullHandling);
|
||||
sort = sort.and(Sort.by(sortOrder));
|
||||
}
|
||||
return sort;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.util.Assert;
|
||||
* BasicQuery for Querydsl
|
||||
*
|
||||
* @author Michael Reiche
|
||||
* @author Tigran Babloyan
|
||||
*/
|
||||
public class BasicQuery extends Query {
|
||||
|
||||
@@ -40,12 +41,11 @@ public class BasicQuery extends Query {
|
||||
* {@link CouchbaseDocument}.
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
* @param projectionFields must not be {@literal null}.
|
||||
* @param projectionFields can be {@literal null}.
|
||||
* @throws IllegalArgumentException when {@code sortObject} or {@code fieldsObject} is {@literal null}.
|
||||
*/
|
||||
public BasicQuery(Query query, Map<String, String> projectionFields) {
|
||||
super(query);
|
||||
Assert.notNull(projectionFields, "Field document must not be null");
|
||||
this.projectionFields = projectionFields;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.data.couchbase.core.CouchbaseOperations;
|
||||
import org.springframework.data.couchbase.core.ExecutableFindByQueryOperation;
|
||||
import org.springframework.data.couchbase.core.query.Query;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -250,7 +251,7 @@ public class SpringDataCouchbaseQuery<T> extends SpringDataCouchbaseQuerySupport
|
||||
@Nullable Expression<?> projection, QueryModifiers modifiers, List<OrderSpecifier<?>> orderBy) {
|
||||
|
||||
Map<String, String> fields = createProjection(projection);
|
||||
BasicQuery basicQuery = new BasicQuery(createCriteria(filter), fields);
|
||||
BasicQuery basicQuery = filter == null ? new BasicQuery(new Query(), fields) : new BasicQuery(createCriteria(filter), fields);
|
||||
|
||||
Integer limit = modifiers.getLimitAsInteger();
|
||||
Integer offset = modifiers.getOffsetAsInteger();
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.querydsl.couchbase.document.CouchbaseDocumentSerializer;
|
||||
|
||||
/**
|
||||
* @author Michael Reiche
|
||||
* @author Tigran Babloyan
|
||||
*/
|
||||
abstract class SpringDataCouchbaseQuerySupport<Q extends SpringDataCouchbaseQuerySupport<Q>>
|
||||
extends AbstractCouchbaseQueryDSL<Q> {
|
||||
@@ -84,10 +85,9 @@ abstract class SpringDataCouchbaseQuerySupport<Q extends SpringDataCouchbaseQuer
|
||||
// sb.append(", ").append(projection.toJson(JSON_WRITER_SETTINGS, codec));
|
||||
// }
|
||||
sb.append(")");
|
||||
// TODO
|
||||
// if (!sort.isEmpty()) {
|
||||
// sb.append(".sort(").append(sort.toJson(JSON_WRITER_SETTINGS, codec)).append(")");
|
||||
// }
|
||||
if (!sort.isEmpty()) {
|
||||
sb.append(".sort(").append(sort).append(")");
|
||||
}
|
||||
if (getQueryMixin().getMetadata().getModifiers().getOffset() != null) {
|
||||
sb.append(".skip(").append(getQueryMixin().getMetadata().getModifiers().getOffset()).append(")");
|
||||
}
|
||||
@@ -128,6 +128,6 @@ abstract class SpringDataCouchbaseQuerySupport<Q extends SpringDataCouchbaseQuer
|
||||
* CouchbaseDocumentSerializer#toSort(List)
|
||||
*/
|
||||
protected Sort createSort(List<OrderSpecifier<?>> orderSpecifiers) {
|
||||
return null; // TODO serializer.toSort(orderSpecifiers);
|
||||
return serializer.toSort(orderSpecifiers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,12 +19,15 @@ package org.springframework.data.couchbase.repository.query;
|
||||
import static com.couchbase.client.java.query.QueryScanConsistency.REQUEST_PLUS;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.springframework.data.couchbase.util.Util.comprises;
|
||||
import static org.springframework.data.couchbase.util.Util.exactly;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
@@ -53,6 +56,7 @@ import org.springframework.data.couchbase.util.Capabilities;
|
||||
import org.springframework.data.couchbase.util.ClusterType;
|
||||
import org.springframework.data.couchbase.util.IgnoreWhen;
|
||||
import org.springframework.data.couchbase.util.JavaIntegrationTests;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
|
||||
@@ -67,6 +71,7 @@ import com.querydsl.core.types.dsl.BooleanExpression;
|
||||
* Repository tests
|
||||
*
|
||||
* @author Michael Reiche
|
||||
* @author Tigran Babloyan
|
||||
*/
|
||||
@SpringJUnitConfig(CouchbaseRepositoryQuerydslIntegrationTests.Config.class)
|
||||
@IgnoreWhen(missesCapabilities = Capabilities.QUERY, clusterTypes = ClusterType.MOCKED)
|
||||
@@ -410,6 +415,72 @@ public class CouchbaseRepositoryQuerydslIntegrationTests extends JavaIntegration
|
||||
assertEquals(" WHERE name in $1", bq(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSort(){
|
||||
{
|
||||
BooleanExpression predicate = airline.name.in(Arrays.stream(saved).map(Airline::getName).toList());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate, Sort.by("name").ascending());
|
||||
assertArrayEquals(StreamSupport.stream(result.spliterator(), false).toArray(Airline[]::new),
|
||||
Arrays.stream(saved)
|
||||
.sorted(Comparator.comparing(Airline::getName))
|
||||
.toArray(Airline[]::new),
|
||||
"Order of airlines does not match");
|
||||
}
|
||||
|
||||
{
|
||||
BooleanExpression predicate = airline.name.in(Arrays.stream(saved).map(Airline::getName).toList());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate, Sort.by("name").descending());
|
||||
assertArrayEquals(StreamSupport.stream(result.spliterator(), false).toArray(Airline[]::new),
|
||||
Arrays.stream(saved)
|
||||
.sorted(Comparator.comparing(Airline::getName).reversed())
|
||||
.toArray(Airline[]::new),
|
||||
"Order of airlines does not match");
|
||||
}
|
||||
|
||||
{
|
||||
BooleanExpression predicate = airline.name.in(Arrays.stream(saved).map(Airline::getName).toList());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate, airline.name.asc());
|
||||
assertArrayEquals(StreamSupport.stream(result.spliterator(), false).toArray(Airline[]::new),
|
||||
Arrays.stream(saved)
|
||||
.sorted(Comparator.comparing(Airline::getName))
|
||||
.toArray(Airline[]::new),
|
||||
"Order of airlines does not match");
|
||||
}
|
||||
|
||||
{
|
||||
BooleanExpression predicate = airline.name.in(Arrays.stream(saved).map(Airline::getName).toList());
|
||||
Iterable<Airline> result = airlineRepository.findAll(predicate, airline.name.desc());
|
||||
assertArrayEquals(StreamSupport.stream(result.spliterator(), false).toArray(Airline[]::new),
|
||||
Arrays.stream(saved)
|
||||
.sorted(Comparator.comparing(Airline::getName).reversed())
|
||||
.toArray(Airline[]::new),
|
||||
"Order of airlines does not match");
|
||||
}
|
||||
|
||||
{
|
||||
Comparator<String> nullSafeStringComparator = Comparator
|
||||
.nullsFirst(String::compareTo);
|
||||
Iterable<Airline> result = airlineRepository.findAll(airline.hqCountry.asc().nullsFirst());
|
||||
assertArrayEquals(StreamSupport.stream(result.spliterator(), false).toArray(Airline[]::new),
|
||||
Arrays.stream(saved)
|
||||
.sorted(Comparator.comparing(Airline::getHqCountry, nullSafeStringComparator))
|
||||
.toArray(Airline[]::new),
|
||||
"Order of airlines does not match");
|
||||
}
|
||||
|
||||
{
|
||||
Comparator<String> nullSafeStringComparator = Comparator
|
||||
.nullsFirst(String::compareTo);
|
||||
Iterable<Airline> result = airlineRepository.findAll(airline.hqCountry.desc().nullsLast());
|
||||
assertArrayEquals(StreamSupport.stream(result.spliterator(), false).toArray(Airline[]::new),
|
||||
Arrays.stream(saved)
|
||||
.sorted(Comparator.comparing(Airline::getHqCountry, nullSafeStringComparator).reversed())
|
||||
.toArray(Airline[]::new),
|
||||
"Order of airlines does not match");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testNotIn() {
|
||||
|
||||
Reference in New Issue
Block a user