DATAMONGO-2416 - Add convenience methods accepting CriteriaDefinition on Fluent API.
The fluent API now exposes default interface methods accepting CriteriaDefinition for a more concise expression of queries that do not require a Query object.
template.query(Person.class).matching(where("firstname").is("luke")).all()
instead of
template.query(Person.class).matching(query(where("firstname").is("luke"))).all()
Original Pull Request: #840
This commit is contained in:
committed by
Christoph Strobl
parent
5fb4b036bb
commit
6387eb9762
@@ -21,6 +21,7 @@ import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.geo.GeoResults;
|
||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
|
||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -170,6 +171,18 @@ public interface ExecutableFindOperation {
|
||||
*/
|
||||
TerminatingFind<T> matching(Query query);
|
||||
|
||||
/**
|
||||
* Set the filter {@link CriteriaDefinition criteria} to be used.
|
||||
*
|
||||
* @param criteriaDefinition must not be {@literal null}.
|
||||
* @return new instance of {@link TerminatingFind}.
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
* @since 3.0
|
||||
*/
|
||||
default TerminatingFind<T> matching(CriteriaDefinition criteriaDefinition) {
|
||||
return matching(Query.query(criteriaDefinition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the filter query for the geoNear execution.
|
||||
*
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.util.List;
|
||||
|
||||
import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind;
|
||||
import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions;
|
||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
|
||||
/**
|
||||
@@ -30,7 +31,7 @@ import org.springframework.data.mongodb.core.query.Query;
|
||||
* The collection to operate on is by default derived from the initial {@literal domainType} and can be defined there
|
||||
* via {@link org.springframework.data.mongodb.core.mapping.Document}. Using {@code inCollection} allows to override the
|
||||
* collection name for the execution.
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* mapReduce(Human.class)
|
||||
@@ -44,6 +45,7 @@ import org.springframework.data.mongodb.core.query.Query;
|
||||
* </pre>
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 2.1
|
||||
*/
|
||||
public interface ExecutableMapReduceOperation {
|
||||
@@ -146,6 +148,18 @@ public interface ExecutableMapReduceOperation {
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
*/
|
||||
TerminatingMapReduce<T> matching(Query query);
|
||||
|
||||
/**
|
||||
* Set the filter {@link CriteriaDefinition criteria} to be used.
|
||||
*
|
||||
* @param criteriaDefinition must not be {@literal null}.
|
||||
* @return new instance of {@link TerminatingMapReduce}.
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
* @since 3.0
|
||||
*/
|
||||
default TerminatingMapReduce<T> matching(CriteriaDefinition criteriaDefinition) {
|
||||
return matching(Query.query(criteriaDefinition));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
|
||||
import com.mongodb.client.result.DeleteResult;
|
||||
@@ -119,6 +120,18 @@ public interface ExecutableRemoveOperation {
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
*/
|
||||
TerminatingRemove<T> matching(Query query);
|
||||
|
||||
/**
|
||||
* Set the filter {@link CriteriaDefinition criteria} to be used.
|
||||
*
|
||||
* @param criteriaDefinition must not be {@literal null}.
|
||||
* @return new instance of {@link TerminatingRemove}.
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
* @since 3.0
|
||||
*/
|
||||
default TerminatingRemove<T> matching(CriteriaDefinition criteriaDefinition) {
|
||||
return matching(Query.query(criteriaDefinition));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
|
||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.data.mongodb.core.query.UpdateDefinition;
|
||||
@@ -210,6 +211,18 @@ public interface ExecutableUpdateOperation {
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
*/
|
||||
UpdateWithUpdate<T> matching(Query query);
|
||||
|
||||
/**
|
||||
* Set the filter {@link CriteriaDefinition criteria} to be used.
|
||||
*
|
||||
* @param criteriaDefinition must not be {@literal null}.
|
||||
* @return new instance of {@link UpdateWithUpdate}.
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
* @since 3.0
|
||||
*/
|
||||
default UpdateWithUpdate<T> matching(CriteriaDefinition criteriaDefinition) {
|
||||
return matching(Query.query(criteriaDefinition));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,7 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.data.geo.GeoResult;
|
||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
|
||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
|
||||
@@ -144,6 +145,18 @@ public interface ReactiveFindOperation {
|
||||
*/
|
||||
TerminatingFind<T> matching(Query query);
|
||||
|
||||
/**
|
||||
* Set the filter {@link CriteriaDefinition criteria} to be used.
|
||||
*
|
||||
* @param criteriaDefinition must not be {@literal null}.
|
||||
* @return new instance of {@link TerminatingFind}.
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
* @since 3.0
|
||||
*/
|
||||
default TerminatingFind<T> matching(CriteriaDefinition criteriaDefinition) {
|
||||
return matching(Query.query(criteriaDefinition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the filter query for the geoNear execution.
|
||||
*
|
||||
|
||||
@@ -19,6 +19,7 @@ import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind;
|
||||
import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions;
|
||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
|
||||
/**
|
||||
@@ -30,7 +31,7 @@ import org.springframework.data.mongodb.core.query.Query;
|
||||
* The collection to operate on is by default derived from the initial {@literal domainType} and can be defined there
|
||||
* via {@link org.springframework.data.mongodb.core.mapping.Document}. Using {@code inCollection} allows to override the
|
||||
* collection name for the execution.
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* mapReduce(Human.class)
|
||||
@@ -146,6 +147,18 @@ public interface ReactiveMapReduceOperation {
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
*/
|
||||
TerminatingMapReduce<T> matching(Query query);
|
||||
|
||||
/**
|
||||
* Set the filter {@link CriteriaDefinition criteria} to be used.
|
||||
*
|
||||
* @param criteriaDefinition must not be {@literal null}.
|
||||
* @return new instance of {@link TerminatingMapReduce}.
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
* @since 3.0
|
||||
*/
|
||||
default TerminatingMapReduce<T> matching(CriteriaDefinition criteriaDefinition) {
|
||||
return matching(Query.query(criteriaDefinition));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
|
||||
import com.mongodb.client.result.DeleteResult;
|
||||
@@ -106,6 +107,18 @@ public interface ReactiveRemoveOperation {
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
*/
|
||||
TerminatingRemove<T> matching(Query query);
|
||||
|
||||
/**
|
||||
* Set the filter {@link CriteriaDefinition criteria} to be used.
|
||||
*
|
||||
* @param criteriaDefinition must not be {@literal null}.
|
||||
* @return new instance of {@link TerminatingRemove}.
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
* @since 3.0
|
||||
*/
|
||||
default TerminatingRemove<T> matching(CriteriaDefinition criteriaDefinition) {
|
||||
return matching(Query.query(criteriaDefinition));
|
||||
}
|
||||
}
|
||||
|
||||
interface ReactiveRemove<T> extends RemoveWithCollection<T> {}
|
||||
|
||||
@@ -15,12 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
|
||||
import org.springframework.data.mongodb.core.query.UpdateDefinition;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
|
||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.data.mongodb.core.query.UpdateDefinition;
|
||||
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
|
||||
@@ -171,6 +172,18 @@ public interface ReactiveUpdateOperation {
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
*/
|
||||
UpdateWithUpdate<T> matching(Query query);
|
||||
|
||||
/**
|
||||
* Set the filter {@link CriteriaDefinition criteria} to be used.
|
||||
*
|
||||
* @param criteriaDefinition must not be {@literal null}.
|
||||
* @return new instance of {@link UpdateWithUpdate}.
|
||||
* @throws IllegalArgumentException if query is {@literal null}.
|
||||
* @since 3.0
|
||||
*/
|
||||
default UpdateWithUpdate<T> matching(CriteriaDefinition criteriaDefinition) {
|
||||
return matching(Query.query(criteriaDefinition));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -95,6 +95,8 @@ public class Query {
|
||||
*/
|
||||
public Query addCriteria(CriteriaDefinition criteriaDefinition) {
|
||||
|
||||
Assert.notNull(criteriaDefinition, "CriteriaDefinition must not be null!");
|
||||
|
||||
CriteriaDefinition existing = this.criteria.get(criteriaDefinition.getKey());
|
||||
String key = criteriaDefinition.getKey();
|
||||
|
||||
|
||||
@@ -169,6 +169,11 @@ public class ExecutableFindOperationSupportTests {
|
||||
assertThat(template.query(Person.class).matching(query(where("firstname").is("luke"))).one()).contains(luke);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2416
|
||||
public void findByCriteria() {
|
||||
assertThat(template.query(Person.class).matching(where("firstname").is("luke")).one()).contains(luke);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1563
|
||||
public void findByNoMatch() {
|
||||
assertThat(template.query(Person.class).matching(query(where("firstname").is("spock"))).one()).isEmpty();
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
@@ -39,6 +40,7 @@ import org.springframework.data.mongodb.core.query.Query;
|
||||
* Unit tests for {@link ExecutableMapReduceOperationSupport}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @currentRead Beyond the Shadows - Brent Weeks
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@@ -109,6 +111,18 @@ public class ExecutableMapReduceOperationSupportUnitTests {
|
||||
isNull(), eq(Person.class));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2416
|
||||
void usesCriteriaWhenPresent() {
|
||||
|
||||
when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS);
|
||||
Query query = Query.query(where("lastname").is("skywalker"));
|
||||
mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION)
|
||||
.matching(where("lastname").is("skywalker")).all();
|
||||
|
||||
verify(template).mapReduce(eq(query), eq(Person.class), eq(STAR_WARS), eq(MAP_FUNCTION), eq(REDUCE_FUNCTION),
|
||||
isNull(), eq(Person.class));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1929
|
||||
void usesProjectionWhenPresent() {
|
||||
|
||||
|
||||
@@ -84,6 +84,14 @@ public class ExecutableRemoveOperationSupportTests {
|
||||
assertThat(result.getDeletedCount()).isEqualTo(1L);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2416
|
||||
public void removeAllMatchingCriteria() {
|
||||
|
||||
DeleteResult result = template.remove(Person.class).matching(where("firstname").is("han")).all();
|
||||
|
||||
assertThat(result.getDeletedCount()).isEqualTo(1L);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1563
|
||||
public void removeAllMatchingWithAlternateDomainTypeAndCollection() {
|
||||
|
||||
|
||||
@@ -120,6 +120,17 @@ public class ExecutableUpdateOperationSupportTests {
|
||||
assertThat(result.getUpsertedId()).isNull();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2416
|
||||
public void updateAllMatchingCriteria() {
|
||||
|
||||
UpdateResult result = template.update(Person.class).matching(where("id").is(han.getId()))
|
||||
.apply(new Update().set("firstname", "Han"))
|
||||
.all();
|
||||
|
||||
assertThat(result.getModifiedCount()).isEqualTo(1L);
|
||||
assertThat(result.getUpsertedId()).isNull();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1563
|
||||
public void updateWithDifferentDomainClassAndCollection() {
|
||||
|
||||
|
||||
@@ -163,6 +163,14 @@ public class ReactiveFindOperationSupportTests {
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2416
|
||||
public void findAllByCriteria() {
|
||||
|
||||
template.query(Person.class).matching(where("firstname").is("luke")).all().as(StepVerifier::create) //
|
||||
.expectNext(luke) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1719
|
||||
public void findAllByWithCollectionUsingMappingInformation() {
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
@@ -39,6 +40,7 @@ import org.springframework.data.mongodb.core.query.Query;
|
||||
* Unit tests for {@link ReactiveMapReduceOperationSupport}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @currentRead Beyond the Shadows - Brent Weeks
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@@ -112,6 +114,19 @@ public class ReactiveMapReduceOperationSupportUnitTests {
|
||||
eq(REDUCE_FUNCTION), isNull());
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2416
|
||||
void usesCriteriaWhenPresent() {
|
||||
|
||||
when(template.getCollectionName(eq(Person.class))).thenReturn(STAR_WARS);
|
||||
|
||||
Query query = Query.query(where("lastname").is("skywalker"));
|
||||
mapReduceOpsSupport.mapReduce(Person.class).map(MAP_FUNCTION).reduce(REDUCE_FUNCTION)
|
||||
.matching(where("lastname").is("skywalker")).all();
|
||||
|
||||
verify(template).mapReduce(eq(query), eq(Person.class), eq(STAR_WARS), eq(Person.class), eq(MAP_FUNCTION),
|
||||
eq(REDUCE_FUNCTION), isNull());
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1929
|
||||
void usesProjectionWhenPresent() {
|
||||
|
||||
|
||||
@@ -85,6 +85,13 @@ public class ReactiveRemoveOperationSupportTests {
|
||||
.consumeNextWith(actual -> assertThat(actual.getDeletedCount()).isEqualTo(1L)).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1719
|
||||
public void removeAllMatchingCriteria() {
|
||||
|
||||
template.remove(Person.class).matching(where("firstname").is("han")).all().as(StepVerifier::create)
|
||||
.consumeNextWith(actual -> assertThat(actual.getDeletedCount()).isEqualTo(1L)).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1719
|
||||
public void removeAllMatchingWithAlternateDomainTypeAndCollection() {
|
||||
|
||||
|
||||
@@ -128,6 +128,17 @@ public class ReactiveUpdateOperationSupportTests {
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2416
|
||||
public void updateAllMatchingCriteria() {
|
||||
|
||||
template.update(Person.class).matching(where("id").is(han.getId())).apply(new Update().set("firstname", "Han"))
|
||||
.all().as(StepVerifier::create).consumeNextWith(actual -> {
|
||||
|
||||
assertThat(actual.getModifiedCount()).isEqualTo(1L);
|
||||
assertThat(actual.getUpsertedId()).isNull();
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1719
|
||||
public void updateWithDifferentDomainClassAndCollection() {
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ class AbstractMongoQueryUnitTests {
|
||||
doReturn(converter).when(mongoOperationsMock).getConverter();
|
||||
doReturn(executableFind).when(mongoOperationsMock).query(any());
|
||||
doReturn(withQueryMock).when(executableFind).as(any());
|
||||
doReturn(withQueryMock).when(withQueryMock).matching(any());
|
||||
doReturn(withQueryMock).when(withQueryMock).matching(any(Query.class));
|
||||
|
||||
when(mongoOperationsMock.remove(any(), any(), anyString())).thenReturn(deleteResultMock);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,10 @@ import org.springframework.data.repository.query.QueryMethodEvaluationContextPro
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractReactiveMongoQuery}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @currentRead Way of Kings - Brandon Sanderson
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@@ -81,7 +84,7 @@ class AbstractReactiveMongoQueryUnitTests {
|
||||
|
||||
doReturn(executableFind).when(mongoOperationsMock).query(any());
|
||||
doReturn(withQueryMock).when(executableFind).as(any());
|
||||
doReturn(withQueryMock).when(withQueryMock).matching(any());
|
||||
doReturn(withQueryMock).when(withQueryMock).matching(any(Query.class));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1854
|
||||
|
||||
Reference in New Issue
Block a user