DATAMONGO-1719 - Polishing.

Use empty query where possible to avoid null values and introduce non optional findAndModify alternative for imperative api.
Add missing ExecutableUpdateOperation Kotlin extension.
Update Javadoc and add non-Javadoc comments.

Original Pull Request: #487
This commit is contained in:
Christoph Strobl
2017-07-21 10:50:30 +02:00
parent 1475cde337
commit 47481c4597
22 changed files with 482 additions and 109 deletions

View File

@@ -51,6 +51,10 @@ class ExecutableAggregationOperationSupport implements ExecutableAggregationOper
this.template = template;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableAggregationOperation#aggregateAndReturn(java.lang.Class)
*/
@Override
public <T> ExecutableAggregation<T> aggregateAndReturn(Class<T> domainType) {
@@ -73,6 +77,10 @@ class ExecutableAggregationOperationSupport implements ExecutableAggregationOper
Aggregation aggregation;
String collection;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableAggregationOperation.AggregationWithCollection#inCollection(java.lang.String)
*/
@Override
public AggregationWithAggregation<T> inCollection(String collection) {
@@ -81,6 +89,10 @@ class ExecutableAggregationOperationSupport implements ExecutableAggregationOper
return new ExecutableAggregationSupport<>(template, domainType, aggregation, collection);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableAggregationOperation.AggregationWithAggregation#by(org.springframework.data.mongodb.core.aggregation.Aggregation)
*/
@Override
public TerminatingAggregation<T> by(Aggregation aggregation) {
@@ -89,11 +101,19 @@ class ExecutableAggregationOperationSupport implements ExecutableAggregationOper
return new ExecutableAggregationSupport<>(template, domainType, aggregation, collection);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableAggregationOperation.TerminatingAggregation#all()
*/
@Override
public AggregationResults<T> all() {
return template.aggregate(aggregation, getCollectionName(aggregation), domainType);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableAggregationOperation.TerminatingAggregation#stream()
*/
@Override
public CloseableIterator<T> stream() {
return template.aggregateStream(aggregation, getCollectionName(aggregation), domainType);

View File

@@ -63,6 +63,10 @@ class ExecutableFindOperationSupport implements ExecutableFindOperation {
this.template = template;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableFindOperation#query(java.lang.Class)
*/
@Override
public <T> ExecutableFind<T> query(Class<T> domainType) {
@@ -87,6 +91,10 @@ class ExecutableFindOperationSupport implements ExecutableFindOperation {
String collection;
Query query;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithCollection#inCollection(java.lang.String)
*/
@Override
public FindWithProjection<T> inCollection(String collection) {
@@ -95,6 +103,10 @@ class ExecutableFindOperationSupport implements ExecutableFindOperation {
return new ExecutableFindSupport<>(template, domainType, returnType, collection, query);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithProjection#as(Class)
*/
@Override
public <T1> FindWithQuery<T1> as(Class<T1> returnType) {
@@ -103,6 +115,10 @@ class ExecutableFindOperationSupport implements ExecutableFindOperation {
return new ExecutableFindSupport<>(template, domainType, returnType, collection, query);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery#matching(org.springframework.data.mongodb.core.query.Query)
*/
@Override
public TerminatingFind<T> matching(Query query) {
@@ -111,6 +127,10 @@ class ExecutableFindOperationSupport implements ExecutableFindOperation {
return new ExecutableFindSupport<>(template, domainType, returnType, collection, query);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableFindOperation.TerminatingFind#oneValue()
*/
@Override
public T oneValue() {
@@ -127,6 +147,10 @@ class ExecutableFindOperationSupport implements ExecutableFindOperation {
return result.iterator().next();
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableFindOperation.TerminatingFind#firstValue()
*/
@Override
public T firstValue() {
@@ -135,26 +159,46 @@ class ExecutableFindOperationSupport implements ExecutableFindOperation {
return ObjectUtils.isEmpty(result) ? null : result.iterator().next();
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableFindOperation.TerminatingFind#all()
*/
@Override
public List<T> all() {
return doFind(null);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableFindOperation.TerminatingFind#stream()
*/
@Override
public Stream<T> stream() {
return StreamUtils.createStreamFromIterator(doStream());
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery#near(org.springframework.data.mongodb.core.query.NearQuery)
*/
@Override
public TerminatingFindNear<T> near(NearQuery nearQuery) {
return () -> template.geoNear(nearQuery, domainType, getCollectionName(), returnType);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableFindOperation.TerminatingFind#count()
*/
@Override
public long count() {
return template.count(query, domainType, getCollectionName());
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableFindOperation.TerminatingFind#exists()
*/
@Override
public boolean exists() {
return template.exists(query, domainType, getCollectionName());
@@ -199,6 +243,10 @@ class ExecutableFindOperationSupport implements ExecutableFindOperation {
this.delegate = delegate;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.CursorPreparer#prepare(com.mongodb.clientFindIterable)
*/
@Override
public FindIterable<Document> prepare(FindIterable<Document> cursor) {

View File

@@ -94,12 +94,6 @@ public interface ExecutableInsertOperation {
BulkWriteResult bulk(Collection<? extends T> objects);
}
/**
* @author Christoph Strobl
* @since 2.0
*/
interface ExecutableInsert<T> extends TerminatingInsert<T>, InsertWithCollection<T>, InsertWithBulkMode<T> {}
/**
* Collection override (optional).
*
@@ -134,4 +128,10 @@ public interface ExecutableInsertOperation {
*/
TerminatingBulkInsert<T> withBulkMode(BulkMode bulkMode);
}
/**
* @author Christoph Strobl
* @since 2.0
*/
interface ExecutableInsert<T> extends TerminatingInsert<T>, InsertWithCollection<T>, InsertWithBulkMode<T> {}
}

View File

@@ -18,11 +18,11 @@ package org.springframework.data.mongodb.core;
import lombok.AccessLevel;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import java.util.ArrayList;
import java.util.Collection;
import lombok.experimental.FieldDefaults;
import org.springframework.data.mongodb.core.BulkOperations.BulkMode;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -53,6 +53,10 @@ class ExecutableInsertOperationSupport implements ExecutableInsertOperation {
this.template = template;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.coreExecutableInsertOperation#insert(java.lan.Class)
*/
@Override
public <T> ExecutableInsert<T> insert(Class<T> domainType) {
@@ -74,6 +78,10 @@ class ExecutableInsertOperationSupport implements ExecutableInsertOperation {
String collection;
BulkMode bulkMode;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableInsertOperation.TerminatingInsert#insert(java.lang.Class)
*/
@Override
public void one(T object) {
@@ -82,6 +90,10 @@ class ExecutableInsertOperationSupport implements ExecutableInsertOperation {
template.insert(object, getCollectionName());
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableInsertOperation.TerminatingInsert#all(java.util.Collection)
*/
@Override
public void all(Collection<? extends T> objects) {
@@ -90,6 +102,10 @@ class ExecutableInsertOperationSupport implements ExecutableInsertOperation {
template.insert(objects, getCollectionName());
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableInsertOperation.TerminatingBulkInsert#bulk(java.util.Collection)
*/
@Override
public BulkWriteResult bulk(Collection<? extends T> objects) {
@@ -99,6 +115,10 @@ class ExecutableInsertOperationSupport implements ExecutableInsertOperation {
.insert(new ArrayList<>(objects)).execute();
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableInsertOperation.InsertWithCollection#inCollection(java.lang.String)
*/
@Override
public InsertWithBulkMode<T> inCollection(String collection) {
@@ -107,6 +127,10 @@ class ExecutableInsertOperationSupport implements ExecutableInsertOperation {
return new ExecutableInsertSupport<>(template, domainType, collection, bulkMode);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableInsertOperation.InsertWithBulkMode#withBulkMode(org.springframework.data.mongodb.core.BulkMode)
*/
@Override
public TerminatingBulkInsert<T> withBulkMode(BulkMode bulkMode) {

View File

@@ -22,8 +22,6 @@ import lombok.experimental.FieldDefaults;
import java.util.List;
import org.bson.Document;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -39,6 +37,8 @@ import com.mongodb.client.result.DeleteResult;
*/
class ExecutableRemoveOperationSupport implements ExecutableRemoveOperation {
private static final Query ALL_QUERY = new Query();
private final MongoTemplate tempate;
/**
@@ -54,12 +54,16 @@ class ExecutableRemoveOperationSupport implements ExecutableRemoveOperation {
this.tempate = template;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableRemoveOperation#remove(java.lang.Class)
*/
@Override
public <T> ExecutableRemove<T> remove(Class<T> domainType) {
Assert.notNull(domainType, "DomainType must not be null!");
return new ExecutableRemoveSupport<>(tempate, domainType, null, null);
return new ExecutableRemoveSupport<>(tempate, domainType, ALL_QUERY, null);
}
/**
@@ -75,6 +79,10 @@ class ExecutableRemoveOperationSupport implements ExecutableRemoveOperation {
Query query;
String collection;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableRemoveOperation.RemoveWithCollection#inCollection(java.lang.String)
*/
@Override
public RemoveWithQuery<T> inCollection(String collection) {
@@ -83,6 +91,10 @@ class ExecutableRemoveOperationSupport implements ExecutableRemoveOperation {
return new ExecutableRemoveSupport<>(template, domainType, query, collection);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableRemoveOperation.RemoveWithQuery#matching(org.springframework.data.mongodb.core.query.Query)
*/
@Override
public TerminatingRemove<T> matching(Query query) {
@@ -91,28 +103,32 @@ class ExecutableRemoveOperationSupport implements ExecutableRemoveOperation {
return new ExecutableRemoveSupport<>(template, domainType, query, collection);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableRemoveOperation.TerminatingRemove#all()
*/
@Override
public DeleteResult all() {
String collectionName = getCollectionName();
return template.doRemove(collectionName, getQuery(), domainType);
return template.doRemove(collectionName, query, domainType);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableRemoveOperation.TerminatingRemove#findAndRemove()
*/
@Override
public List<T> findAndRemove() {
String collectionName = getCollectionName();
return template.doFindAndDelete(collectionName, getQuery(), domainType);
return template.doFindAndDelete(collectionName, query, domainType);
}
private String getCollectionName() {
return StringUtils.hasText(collection) ? collection : template.determineCollectionName(domainType);
}
private Query getQuery() {
return query != null ? query : new BasicQuery(new Document());
}
}
}

View File

@@ -56,12 +56,6 @@ public interface ExecutableUpdateOperation {
*/
<T> ExecutableUpdate<T> update(Class<T> domainType);
/**
* @author Christoph Strobl
* @since 2.0
*/
interface ExecutableUpdate<T> extends UpdateWithCollection<T>, UpdateWithQuery<T>, UpdateWithUpdate<T> {}
/**
* Declare the {@link Update} to apply.
*
@@ -145,7 +139,16 @@ public interface ExecutableUpdateOperation {
*
* @return {@link Optional#empty()} if nothing found.
*/
Optional<T> findAndModify();
default Optional<T> findAndModify() {
return Optional.ofNullable(findAndModifyValue());
}
/**
* Find, modify and return the first matching document.
*
* @return {@literal null} if nothing found.
*/
T findAndModifyValue();
}
/**
@@ -177,4 +180,10 @@ public interface ExecutableUpdateOperation {
*/
UpdateResult upsert();
}
/**
* @author Christoph Strobl
* @since 2.0
*/
interface ExecutableUpdate<T> extends UpdateWithCollection<T>, UpdateWithQuery<T>, UpdateWithUpdate<T> {}
}

View File

@@ -20,10 +20,6 @@ import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import java.util.Optional;
import org.bson.Document;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.util.Assert;
@@ -40,6 +36,8 @@ import com.mongodb.client.result.UpdateResult;
*/
class ExecutableUpdateOperationSupport implements ExecutableUpdateOperation {
private static final Query ALL_QUERY = new Query();
private final MongoTemplate template;
/**
@@ -54,12 +52,16 @@ class ExecutableUpdateOperationSupport implements ExecutableUpdateOperation {
this.template = template;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableUpdateOperation#update(java.lang.Class)
*/
@Override
public <T> ExecutableUpdate<T> update(Class<T> domainType) {
Assert.notNull(domainType, "DomainType must not be null!");
return new ExecutableUpdateSupport<>(template, domainType, null, null, null, null);
return new ExecutableUpdateSupport<>(template, domainType, ALL_QUERY, null, null, null);
}
/**
@@ -78,6 +80,10 @@ class ExecutableUpdateOperationSupport implements ExecutableUpdateOperation {
String collection;
FindAndModifyOptions options;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableUpdateOperation.UpdateWithUpdate#apply(Update)
*/
@Override
public TerminatingUpdate<T> apply(Update update) {
@@ -86,6 +92,10 @@ class ExecutableUpdateOperationSupport implements ExecutableUpdateOperation {
return new ExecutableUpdateSupport<>(template, domainType, query, update, collection, options);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableUpdateOperation.UpdateWithCollection#inCollection(java.lang.String)
*/
@Override
public UpdateWithQuery<T> inCollection(String collection) {
@@ -94,38 +104,10 @@ class ExecutableUpdateOperationSupport implements ExecutableUpdateOperation {
return new ExecutableUpdateSupport<>(template, domainType, query, update, collection, options);
}
@Override
public UpdateResult first() {
return doUpdate(false, false);
}
@Override
public UpdateResult upsert() {
return doUpdate(true, true);
}
@Override
public Optional<T> findAndModify() {
String collectionName = getCollectionName();
return Optional.ofNullable(template.findAndModify(query != null ? query : new BasicQuery(new Document()), update,
options, domainType, collectionName));
}
@Override
public UpdateWithUpdate<T> matching(Query query) {
Assert.notNull(query, "Query must not be null!");
return new ExecutableUpdateSupport<>(template, domainType, query, update, collection, options);
}
@Override
public UpdateResult all() {
return doUpdate(true, false);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableUpdateOperation.FindAndModifyWithOptions#withOptions(org.springframework.data.mongodb.core.FindAndModifyOptions)
*/
@Override
public TerminatingFindAndModify<T> withOptions(FindAndModifyOptions options) {
@@ -134,13 +116,56 @@ class ExecutableUpdateOperationSupport implements ExecutableUpdateOperation {
return new ExecutableUpdateSupport<>(template, domainType, query, update, collection, options);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveUpdateOperation.UpdateWithQuery#matching(org.springframework.data.mongodb.core.query.Query)
*/
@Override
public UpdateWithUpdate<T> matching(Query query) {
Assert.notNull(query, "Query must not be null!");
return new ExecutableUpdateSupport<>(template, domainType, query, update, collection, options);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableUpdateOperation.TerminatingUpdate#all()
*/
@Override
public UpdateResult all() {
return doUpdate(true, false);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableUpdateOperation.TerminatingUpdate#first()
*/
@Override
public UpdateResult first() {
return doUpdate(false, false);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableUpdateOperation.TerminatingUpdate#upsert()
*/
@Override
public UpdateResult upsert() {
return doUpdate(true, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableUpdateOperation.TerminatingFindAndModify#findAndModifyValue()
*/
@Override
public T findAndModifyValue() {
return template.findAndModify(query, update, options, domainType, getCollectionName());
}
private UpdateResult doUpdate(boolean multi, boolean upsert) {
String collectionName = getCollectionName();
Query query = this.query != null ? this.query : new BasicQuery(new Document());
return template.doUpdate(collectionName, query, update, domainType, upsert, multi);
return template.doUpdate(getCollectionName(), query, update, domainType, upsert, multi);
}
private String getCollectionName() {

View File

@@ -36,6 +36,7 @@ import org.springframework.data.mongodb.core.aggregation.Aggregation;
* </pre>
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
public interface ReactiveAggregationOperation {
@@ -46,7 +47,7 @@ public interface ReactiveAggregationOperation {
* input type for he aggregation.
*
* @param domainType must not be {@literal null}.
* @return new instance of {@link ReactiveAggregation}.
* @return new instance of {@link ReactiveAggregation}. Never {@literal null}.
* @throws IllegalArgumentException if domainType is {@literal null}.
*/
<T> ReactiveAggregation<T> aggregateAndReturn(Class<T> domainType);
@@ -61,8 +62,8 @@ public interface ReactiveAggregationOperation {
* Skip this step to use the default collection derived from the domain type.
*
* @param collection must not be {@literal null} nor {@literal empty}.
* @return new instance of {@link AggregationOperationWithAggregation}.
* @throws IllegalArgumentException if collection is {@literal null}.
* @return new instance of {@link AggregationOperationWithAggregation}. Never {@literal null}.
* @throws IllegalArgumentException if collection is {@literal null} or empty.
*/
AggregationOperationWithAggregation<T> inCollection(String collection);
}
@@ -89,7 +90,7 @@ public interface ReactiveAggregationOperation {
* Set the aggregation to be used.
*
* @param aggregation must not be {@literal null}.
* @return new instance of {@link TerminatingAggregationOperation}.
* @return new instance of {@link TerminatingAggregationOperation}. Never {@literal null}.
* @throws IllegalArgumentException if aggregation is {@literal null}.
*/
TerminatingAggregationOperation<T> by(Aggregation aggregation);

View File

@@ -27,9 +27,10 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Implementation of {@link ExecutableAggregationOperation} operating directly on {@link ReactiveMongoTemplate}.
* Implementation of {@link ReactiveAggregationOperation} operating directly on {@link ReactiveMongoTemplate}.
*
* @author Mark Paluch
* @autor Christoph Strobl
* @since 2.0
*/
class ReactiveAggregationOperationSupport implements ReactiveAggregationOperation {
@@ -49,6 +50,10 @@ class ReactiveAggregationOperationSupport implements ReactiveAggregationOperatio
this.template = template;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveAggregationOperation#aggregateAndReturn(java.lang.Class)
*/
@Override
public <T> ReactiveAggregation<T> aggregateAndReturn(Class<T> domainType) {
@@ -67,6 +72,10 @@ class ReactiveAggregationOperationSupport implements ReactiveAggregationOperatio
Aggregation aggregation;
String collection;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveAggregationOperation.AggregationOperationWithCollection#inCollection(java.lang.String)
*/
@Override
public AggregationOperationWithAggregation<T> inCollection(String collection) {
@@ -75,6 +84,10 @@ class ReactiveAggregationOperationSupport implements ReactiveAggregationOperatio
return new ReactiveAggregationSupport<>(template, domainType, aggregation, collection);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveAggregationOperation.AggregationOperationWithAggregation#by(org.springframework.data.mongodb.core.Aggregation)
*/
@Override
public TerminatingAggregationOperation<T> by(Aggregation aggregation) {
@@ -83,6 +96,10 @@ class ReactiveAggregationOperationSupport implements ReactiveAggregationOperatio
return new ReactiveAggregationSupport<>(template, domainType, aggregation, collection);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveAggregationOperation.TerminatingAggregationOperation#all()
*/
@Override
public Flux<T> all() {
return template.aggregate(aggregation, getCollectionName(aggregation), domainType);

View File

@@ -44,6 +44,7 @@ import org.springframework.data.mongodb.core.query.Query;
* </pre>
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
public interface ReactiveFindOperation {
@@ -52,7 +53,7 @@ public interface ReactiveFindOperation {
* Start creating a find operation for the given {@literal domainType}.
*
* @param domainType must not be {@literal null}.
* @return new instance of {@link ReactiveFind}.
* @return new instance of {@link ReactiveFind}. Never {@literal null}.
* @throws IllegalArgumentException if domainType is {@literal null}.
*/
<T> ReactiveFind<T> query(Class<T> domainType);
@@ -65,7 +66,7 @@ public interface ReactiveFindOperation {
/**
* Get exactly zero or one result.
*
* @return {@link Mono#empty()} if no match found.
* @return {@link Mono#empty()} if no match found. Never {@literal null}.
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one match found.
*/
Mono<T> one();
@@ -73,7 +74,7 @@ public interface ReactiveFindOperation {
/**
* Get the first or no result.
*
* @return {@link Mono#empty()} if no match found.
* @return {@link Mono#empty()} if no match found. Never {@literal null}.
*/
Mono<T> first();
@@ -87,14 +88,14 @@ public interface ReactiveFindOperation {
/**
* Get the number of matching elements.
*
* @return total number of matching elements.
* @return {@link Mono} emitting total number of matching elements. Never {@literal null}.
*/
Mono<Long> count();
/**
* Check for the presence of matching elements.
*
* @return {@literal true} if at least one matching element exists.
* @return {@link Mono} emitting {@literal true} if at least one matching element exists. Never {@literal null}.
*/
Mono<Boolean> exists();
}

View File

@@ -36,6 +36,7 @@ import com.mongodb.reactivestreams.client.FindPublisher;
* Implementation of {@link ReactiveFindOperation}.
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
@RequiredArgsConstructor
@@ -45,6 +46,10 @@ class ReactiveFindOperationSupport implements ReactiveFindOperation {
private final @NonNull ReactiveMongoTemplate template;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveFindOperation#query(java.lang.Class)
*/
@Override
public <T> ReactiveFind<T> query(Class<T> domainType) {
@@ -55,6 +60,7 @@ class ReactiveFindOperationSupport implements ReactiveFindOperation {
/**
* @param <T>
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
@@ -69,6 +75,10 @@ class ReactiveFindOperationSupport implements ReactiveFindOperation {
String collection;
Query query;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveFindOperation.FindWithCollection#inCollection(java.lang.String)
*/
@Override
public FindWithProjection<T> inCollection(String collection) {
@@ -77,6 +87,10 @@ class ReactiveFindOperationSupport implements ReactiveFindOperation {
return new ReactiveFindSupport<>(template, domainType, returnType, collection, query);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveFindOperation.FindWithProjection#as(java.lang.Class)
*/
@Override
public <T1> FindWithQuery<T1> as(Class<T1> returnType) {
@@ -85,6 +99,10 @@ class ReactiveFindOperationSupport implements ReactiveFindOperation {
return new ReactiveFindSupport<>(template, domainType, returnType, collection, query);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveFindOperation.FindWithQuery#matching(org.springframework.data.mongodb.core.query.Query)
*/
@Override
public TerminatingFind<T> matching(Query query) {
@@ -93,6 +111,10 @@ class ReactiveFindOperationSupport implements ReactiveFindOperation {
return new ReactiveFindSupport<>(template, domainType, returnType, collection, query);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveFindOperation.TerminatingFind#first()
*/
@Override
public Mono<T> first() {
@@ -107,6 +129,10 @@ class ReactiveFindOperationSupport implements ReactiveFindOperation {
return result.next();
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveFindOperation.TerminatingFind#one()
*/
@Override
public Mono<T> one() {
@@ -133,21 +159,37 @@ class ReactiveFindOperationSupport implements ReactiveFindOperation {
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveFindOperation.TerminatingFind#all()
*/
@Override
public Flux<T> all() {
return doFind(null);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveFindOperation.FindWithQuery#near(org.springframework.data.mongodb.core.query.NearQuery)
*/
@Override
public TerminatingFindNear<T> near(NearQuery nearQuery) {
return () -> template.geoNear(nearQuery, domainType, getCollectionName(), returnType);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveFindOperation.TerminatingFind#count()
*/
@Override
public Mono<Long> count() {
return template.count(query, domainType, getCollectionName());
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveFindOperation.TerminatingFind#exists()
*/
@Override
public Mono<Boolean> exists() {
return template.exists(query, domainType, getCollectionName());

View File

@@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core;
/**
* Stripped down interface providing access to a fluent API that specifies a basic set of reactive MongoDB operations.
*
* @author Mark Paluch
* @since 2.0
*/
public interface ReactiveFluentMongoOperations extends ReactiveFindOperation, ReactiveInsertOperation,

View File

@@ -36,6 +36,7 @@ import java.util.Collection;
* </pre>
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
public interface ReactiveInsertOperation {
@@ -44,7 +45,7 @@ public interface ReactiveInsertOperation {
* Start creating an insert operation for given {@literal domainType}.
*
* @param domainType must not be {@literal null}.
* @return new instance of {@link ReactiveInsert}.
* @return new instance of {@link ReactiveInsert}. Never {@literal null}.
* @throws IllegalArgumentException if domainType is {@literal null}.
*/
<T> ReactiveInsert<T> insert(Class<T> domainType);
@@ -58,6 +59,7 @@ public interface ReactiveInsertOperation {
* Insert exactly one object.
*
* @param object must not be {@literal null}.
* @return {@link Mono} emitting the inserted {@code object} when operation has completed. Never {@literal null}.
* @throws IllegalArgumentException if object is {@literal null}.
*/
Mono<T> one(T object);
@@ -66,13 +68,12 @@ public interface ReactiveInsertOperation {
* Insert a collection of objects.
*
* @param objects must not be {@literal null}.
* @return {@literal Flux} emitting the inserted {@code objects} ony by one. Never {@literal null}.
* @throws IllegalArgumentException if objects is {@literal null}.
*/
Flux<T> all(Collection<? extends T> objects);
}
interface ReactiveInsert<T> extends TerminatingInsert<T>, InsertWithCollection<T> {}
/**
* Collection override (optional).
*/
@@ -83,9 +84,11 @@ public interface ReactiveInsertOperation {
* Skip this step to use the default collection derived from the domain type.
*
* @param collection must not be {@literal null} nor {@literal empty}.
* @return new instance of {@link TerminatingInsert}.
* @return new instance of {@link TerminatingInsert}. Never {@literal null}.
* @throws IllegalArgumentException if collection is {@literal null}.
*/
TerminatingInsert<T> inCollection(String collection);
}
interface ReactiveInsert<T> extends TerminatingInsert<T>, InsertWithCollection<T> {}
}

View File

@@ -31,6 +31,7 @@ import org.springframework.util.StringUtils;
* Implementation of {@link ReactiveInsertOperation}.
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
@RequiredArgsConstructor
@@ -38,6 +39,10 @@ class ReactiveInsertOperationSupport implements ReactiveInsertOperation {
private final @NonNull ReactiveMongoTemplate template;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveInsertOperation#insert(java.lang.Class)
*/
@Override
public <T> ReactiveInsert<T> insert(Class<T> domainType) {
@@ -54,6 +59,10 @@ class ReactiveInsertOperationSupport implements ReactiveInsertOperation {
@NonNull Class<T> domainType;
String collection;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveInsertOperation.TerminatingInsert#one(java.lang.Object)
*/
@Override
public Mono<T> one(T object) {
@@ -62,6 +71,10 @@ class ReactiveInsertOperationSupport implements ReactiveInsertOperation {
return template.insert(object, getCollectionName());
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveInsertOperation.TerminatingInsert#all(java.util.Collection)
*/
@Override
public Flux<T> all(Collection<? extends T> objects) {
@@ -70,6 +83,10 @@ class ReactiveInsertOperationSupport implements ReactiveInsertOperation {
return template.insert(objects, getCollectionName());
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveInsertOperation.InsertWithCollection#inCollection(java.lang.String)
*/
@Override
public ReactiveInsert<T> inCollection(String collection) {

View File

@@ -40,6 +40,7 @@ import com.mongodb.client.result.DeleteResult;
* </pre>
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
public interface ReactiveRemoveOperation {
@@ -48,7 +49,7 @@ public interface ReactiveRemoveOperation {
* Start creating a remove operation for the given {@literal domainType}.
*
* @param domainType must not be {@literal null}.
* @return new instance of {@link ReactiveRemove}.
* @return new instance of {@link ReactiveRemove}. Never {@literal null}.
* @throws IllegalArgumentException if domainType is {@literal null}.
*/
<T> ReactiveRemove<T> remove(Class<T> domainType);
@@ -61,7 +62,7 @@ public interface ReactiveRemoveOperation {
/**
* Remove all documents matching.
*
* @return the {@link DeleteResult}. Never {@literal null}.
* @return {@link Mono} emitting the {@link DeleteResult}. Never {@literal null}.
*/
Mono<DeleteResult> all();
@@ -86,8 +87,8 @@ public interface ReactiveRemoveOperation {
* Skip this step to use the default collection derived from the domain type.
*
* @param collection must not be {@literal null} nor {@literal empty}.
* @return new instance of {@link RemoveWithCollection}.
* @throws IllegalArgumentException if collection is {@literal null}.
* @return new instance of {@link RemoveWithCollection}. Never {@literal null}.
* @throws IllegalArgumentException if collection is {@literal null} or empty.
*/
RemoveWithQuery<T> inCollection(String collection);
}
@@ -101,7 +102,7 @@ public interface ReactiveRemoveOperation {
* Define the query filtering elements.
*
* @param query must not be {@literal null}.
* @return new instance of {@link TerminatingRemove}.
* @return new instance of {@link TerminatingRemove}. Never {@literal null}.
* @throws IllegalArgumentException if query is {@literal null}.
*/
TerminatingRemove<T> matching(Query query);

View File

@@ -32,6 +32,7 @@ import com.mongodb.client.result.DeleteResult;
* Implementation of {@link ReactiveRemoveOperation}.
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
@RequiredArgsConstructor
@@ -41,12 +42,16 @@ class ReactiveRemoveOperationSupport implements ReactiveRemoveOperation {
private final @NonNull ReactiveMongoTemplate tempate;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveRemoveOperation#remove(java.lang.Class)
*/
@Override
public <T> ReactiveRemove<T> remove(Class<T> domainType) {
Assert.notNull(domainType, "DomainType must not be null!");
return new ReactiveRemoveSupport<>(tempate, domainType, null, null);
return new ReactiveRemoveSupport<>(tempate, domainType, ALL_QUERY, null);
}
@RequiredArgsConstructor
@@ -58,6 +63,10 @@ class ReactiveRemoveOperationSupport implements ReactiveRemoveOperation {
Query query;
String collection;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveRemoveOperation.RemoveWithCollection#inCollection(String)
*/
@Override
public RemoveWithQuery<T> inCollection(String collection) {
@@ -66,6 +75,10 @@ class ReactiveRemoveOperationSupport implements ReactiveRemoveOperation {
return new ReactiveRemoveSupport<>(template, domainType, query, collection);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveRemoveOperation.RemoveWithQuery#matching(org.springframework.data.mongodb.core.Query)
*/
@Override
public TerminatingRemove<T> matching(Query query) {
@@ -74,28 +87,33 @@ class ReactiveRemoveOperationSupport implements ReactiveRemoveOperation {
return new ReactiveRemoveSupport<>(template, domainType, query, collection);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveRemoveOperation.TerminatingRemove#all()
*/
@Override
public Mono<DeleteResult> all() {
String collectionName = getCollectionName();
return template.doRemove(collectionName, getQuery(), domainType);
return template.doRemove(collectionName, query, domainType);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveRemoveOperation.TerminatingRemove#findAndRemove()
*/
@Override
public Flux<T> findAndRemove() {
String collectionName = getCollectionName();
return template.doFindAndDelete(collectionName, getQuery(), domainType);
return template.doFindAndDelete(collectionName, query, domainType);
}
private String getCollectionName() {
return StringUtils.hasText(collection) ? collection : template.determineCollectionName(domainType);
}
private Query getQuery() {
return query != null ? query : ALL_QUERY;
}
}
}

View File

@@ -41,6 +41,7 @@ import com.mongodb.client.result.UpdateResult;
* </pre>
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
public interface ReactiveUpdateOperation {
@@ -49,7 +50,7 @@ public interface ReactiveUpdateOperation {
* Start creating an update operation for the given {@literal domainType}.
*
* @param domainType must not be {@literal null}.
* @return new instance of {@link ReactiveUpdate}.
* @return new instance of {@link ReactiveUpdate}. Never {@literal null}.
* @throws IllegalArgumentException if domainType is {@literal null}.
*/
<T> ReactiveUpdate<T> update(Class<T> domainType);
@@ -62,7 +63,7 @@ public interface ReactiveUpdateOperation {
/**
* Find, modify and return the first matching document.
*
* @return {@link Mono#empty()} if nothing found.
* @return {@link Mono#empty()} if nothing found. Never {@literal null}.
*/
Mono<T> findAndModify();
}
@@ -94,8 +95,6 @@ public interface ReactiveUpdateOperation {
Mono<UpdateResult> upsert();
}
interface ReactiveUpdate<T> extends UpdateWithCollection<T>, UpdateWithQuery<T>, UpdateWithUpdate<T> {}
/**
* Declare the {@link org.springframework.data.mongodb.core.query.Update} to apply.
*/
@@ -105,7 +104,7 @@ public interface ReactiveUpdateOperation {
* Set the {@link org.springframework.data.mongodb.core.query.Update} to be applied.
*
* @param update must not be {@literal null}.
* @return new instance of {@link TerminatingUpdate}.
* @return new instance of {@link TerminatingUpdate}. Never {@literal null}.
* @throws IllegalArgumentException if update is {@literal null}.
*/
TerminatingUpdate<T> apply(org.springframework.data.mongodb.core.query.Update update);
@@ -121,8 +120,8 @@ public interface ReactiveUpdateOperation {
* Skip this step to use the default collection derived from the domain type.
*
* @param collection must not be {@literal null} nor {@literal empty}.
* @return new instance of {@link UpdateWithCollection}.
* @throws IllegalArgumentException if collection is {@literal null}.
* @return new instance of {@link UpdateWithCollection}. Never {@literal null}.
* @throws IllegalArgumentException if collection is {@literal null} or empty.
*/
UpdateWithQuery<T> inCollection(String collection);
}
@@ -136,7 +135,7 @@ public interface ReactiveUpdateOperation {
* Filter documents by given {@literal query}.
*
* @param query must not be {@literal null}.
* @return new instance of {@link UpdateWithQuery}.
* @return new instance of {@link UpdateWithQuery}. Never {@literal null}.
* @throws IllegalArgumentException if query is {@literal null}.
*/
UpdateWithUpdate<T> matching(Query query);
@@ -152,9 +151,11 @@ public interface ReactiveUpdateOperation {
* {@link org.springframework.data.mongodb.core.query.Update}.
*
* @param options must not be {@literal null}.
* @return new instance of {@link FindAndModifyWithOptions}.
* @return new instance of {@link TerminatingFindAndModify}. Never {@literal null}.
* @throws IllegalArgumentException if options is {@literal null}.
*/
TerminatingFindAndModify<T> withOptions(FindAndModifyOptions options);
}
interface ReactiveUpdate<T> extends UpdateWithCollection<T>, UpdateWithQuery<T>, UpdateWithUpdate<T> {}
}

View File

@@ -31,6 +31,7 @@ import com.mongodb.client.result.UpdateResult;
* Implementation of {@link ReactiveUpdateOperation}.
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
@RequiredArgsConstructor
@@ -40,12 +41,16 @@ class ReactiveUpdateOperationSupport implements ReactiveUpdateOperation {
private final @NonNull ReactiveMongoTemplate template;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveUpdateOperation#update(java.lang.Class)
*/
@Override
public <T> ReactiveUpdate<T> update(Class<T> domainType) {
Assert.notNull(domainType, "DomainType must not be null!");
return new ReactiveUpdateSupport<>(template, domainType, null, null, null, null);
return new ReactiveUpdateSupport<>(template, domainType, ALL_QUERY, null, null, null);
}
@RequiredArgsConstructor
@@ -60,6 +65,10 @@ class ReactiveUpdateOperationSupport implements ReactiveUpdateOperation {
String collection;
FindAndModifyOptions options;
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveUpdateOperation.UpdateWithUpdate#apply(org.springframework.data.mongodb.core.query.Update)
*/
@Override
public TerminatingUpdate<T> apply(org.springframework.data.mongodb.core.query.Update update) {
@@ -68,6 +77,10 @@ class ReactiveUpdateOperationSupport implements ReactiveUpdateOperation {
return new ReactiveUpdateSupport<>(template, domainType, query, update, collection, options);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveUpdateOperation.UpdateWithCollection#inCollection(java.lang.String)
*/
@Override
public UpdateWithQuery<T> inCollection(String collection) {
@@ -76,24 +89,40 @@ class ReactiveUpdateOperationSupport implements ReactiveUpdateOperation {
return new ReactiveUpdateSupport<>(template, domainType, query, update, collection, options);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveUpdateOperation.TerminatingUpdate#first()
*/
@Override
public Mono<UpdateResult> first() {
return doUpdate(false, false);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveUpdateOperation.TerminatingUpdate#upsert()
*/
@Override
public Mono<UpdateResult> upsert() {
return doUpdate(true, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveUpdateOperation.TerminatingFindAndModify#findAndModify()
*/
@Override
public Mono<T> findAndModify() {
String collectionName = getCollectionName();
return template.findAndModify(query != null ? query : ALL_QUERY, update, options, domainType, collectionName);
return template.findAndModify(query, update, options, domainType, collectionName);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveUpdateOperation.UpdateWithQuery#matching(org.springframework.data.mongodb.core.Query)
*/
@Override
public UpdateWithUpdate<T> matching(Query query) {
@@ -102,11 +131,19 @@ class ReactiveUpdateOperationSupport implements ReactiveUpdateOperation {
return new ReactiveUpdateSupport<>(template, domainType, query, update, collection, options);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveUpdateOperation.TerminatingUpdate#all()
*/
@Override
public Mono<UpdateResult> all() {
return doUpdate(true, false);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveUpdateOperation.FindAndModifyWithOptions#withOptions(org.springframework.data.mongodb.core.FindAndModifyOptions)
*/
@Override
public TerminatingFindAndModify<T> withOptions(FindAndModifyOptions options) {
@@ -116,12 +153,7 @@ class ReactiveUpdateOperationSupport implements ReactiveUpdateOperation {
}
private Mono<UpdateResult> doUpdate(boolean multi, boolean upsert) {
String collectionName = getCollectionName();
Query query = this.query != null ? this.query : ALL_QUERY;
return template.doUpdate(collectionName, query, update, domainType, upsert, multi);
return template.doUpdate(getCollectionName(), query, update, domainType, upsert, multi);
}
private String getCollectionName() {

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2017 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
*
* http://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 kotlin.reflect.KClass
/**
* Extension for [ExecutableUpdateOperation.update] providing a [KClass] based variant.
*
* @author Christoph Strobl
* @since 2.0
*/
fun <T : Any> ExecutableUpdateOperation.update(entityClass: KClass<T>): ExecutableUpdateOperation.ExecutableUpdate<T> =
update(entityClass.java)
/**
* Extension for [ExecutableUpdateOperation.update] leveraging reified type parameters.
*
* @author Christoph Strobl
* @since 2.0
*/
inline fun <reified T : Any> ExecutableUpdateOperation.update(): ExecutableUpdateOperation.ExecutableUpdate<T> =
update(T::class.java)

View File

@@ -27,7 +27,7 @@ fun <T : Any> ReactiveUpdateOperation.update(entityClass: KClass<T>): ReactiveUp
update(entityClass.java)
/**
* Extension for [ReactiveUpdateOperation.insert] leveraging reified type parameters.
* Extension for [ReactiveUpdateOperation.update] leveraging reified type parameters.
*
* @author Mark Paluch
* @since 2.0

View File

@@ -126,6 +126,17 @@ public class ExecutableUpdateOperationSupportTests {
"Han");
}
@Test // DATAMONGO-1719
public void findAndModifyValue() {
Person result = template.update(Person.class).matching(queryHan()).apply(new Update().set("firstname", "Han"))
.findAndModifyValue();
assertThat(result).isEqualTo(han);
assertThat(template.findOne(queryHan(), Person.class)).isNotEqualTo(han).hasFieldOrPropertyWithValue("firstname",
"Han");
}
@Test // DATAMONGO-1563
public void findAndModify() {

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2017 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
*
* http://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 com.nhaarman.mockito_kotlin.verify
import example.first.First
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Answers
import org.mockito.Mock
import org.mockito.junit.MockitoJUnitRunner
/**
* Unit tests for [ExecutableUpdateOperationExtensions].
*
* @author Christoph Strobl
*/
@RunWith(MockitoJUnitRunner::class)
class ExecutableUpdateOperationExtensionsTests {
@Mock(answer = Answers.RETURNS_MOCKS)
lateinit var operation: ExecutableUpdateOperation
@Test // DATAMONGO-1719
fun `update(KClass) extension should call its Java counterpart`() {
operation.update(First::class)
verify(operation).update(First::class.java)
}
@Test // DATAMONGO-1719
fun `update() with reified type parameter extension should call its Java counterpart`() {
operation.update<First>()
verify(operation).update(First::class.java)
}
}