Skip to content

Commit 30b86e7

Browse files
DATAMONGO-1311 - Polishing.
Update Javadoc and add reference documentation. Alter @meta batchSize default to zero, as negative values bear a special meaning. Along the lines remove deprecated driver method usage and add deprecations for options about the be removed in subsequent MongoDB server releases. Original Pull Request: spring-projects#575
1 parent d3976f5 commit 30b86e7

File tree

13 files changed

+183
-241
lines changed

13 files changed

+183
-241
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java

Lines changed: 20 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -3281,8 +3281,7 @@ public FindIterable<Document> prepare(FindIterable<Document> cursor) {
32813281

32823282
Meta meta = query.getMeta();
32833283
if (query.getSkip() <= 0 && query.getLimit() <= 0 && ObjectUtils.isEmpty(query.getSortObject())
3284-
&& !StringUtils.hasText(query.getHint()) && !meta.hasValues()
3285-
&& !query.getCollation().isPresent()) {
3284+
&& !StringUtils.hasText(query.getHint()) && !meta.hasValues() && !query.getCollation().isPresent()) {
32863285
return cursor;
32873286
}
32883287

@@ -3302,15 +3301,30 @@ public FindIterable<Document> prepare(FindIterable<Document> cursor) {
33023301
cursorToUse = cursorToUse.sort(sort);
33033302
}
33043303

3305-
Document metaDocument = new Document();
33063304
if (StringUtils.hasText(query.getHint())) {
3307-
metaDocument.put("$hint", query.getHint());
3305+
cursorToUse = cursorToUse.hint(Document.parse(query.getHint()));
33083306
}
33093307

33103308
if (meta.hasValues()) {
33113309

3312-
for (Entry<String, Object> entry : meta.values()) {
3313-
metaDocument.put(entry.getKey(), entry.getValue());
3310+
if (StringUtils.hasText(meta.getComment())) {
3311+
cursorToUse = cursorToUse.comment(meta.getComment());
3312+
}
3313+
3314+
if (meta.getSnapshot()) {
3315+
cursorToUse = cursorToUse.snapshot(meta.getSnapshot());
3316+
}
3317+
3318+
if (meta.getMaxScan() != null) {
3319+
cursorToUse = cursorToUse.maxScan(meta.getMaxScan());
3320+
}
3321+
3322+
if (meta.getMaxTimeMsec() != null) {
3323+
cursorToUse = cursorToUse.maxTime(meta.getMaxTimeMsec(), TimeUnit.MILLISECONDS);
3324+
}
3325+
3326+
if (meta.getCursorBatchSize() != null) {
3327+
cursorToUse = cursorToUse.batchSize(meta.getCursorBatchSize());
33143328
}
33153329

33163330
for (Meta.CursorOption option : meta.getFlags()) {
@@ -3327,13 +3341,8 @@ public FindIterable<Document> prepare(FindIterable<Document> cursor) {
33273341
throw new IllegalArgumentException(String.format("%s is no supported flag.", option));
33283342
}
33293343
}
3330-
3331-
if (meta.getCursorBatchSize() != null) {
3332-
cursorToUse = cursorToUse.batchSize(meta.getCursorBatchSize());
3333-
}
33343344
}
33353345

3336-
cursorToUse = cursorToUse.modifiers(metaDocument);
33373346
} catch (RuntimeException e) {
33383347
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
33393348
}
@@ -3464,149 +3473,6 @@ public MongoDbFactory getMongoDbFactory() {
34643473
return mongoDbFactory;
34653474
}
34663475

3467-
/**
3468-
* {@link BatchAggregationLoader} is a little helper that can process cursor results returned by an aggregation
3469-
* command execution. On presence of a {@literal nextBatch} indicated by presence of an {@code id} field in the
3470-
* {@code cursor} another {@code getMore} command gets executed reading the next batch of documents until all results
3471-
* are loaded.
3472-
*
3473-
* @author Christoph Strobl
3474-
* @since 1.10
3475-
*/
3476-
static class BatchAggregationLoader {
3477-
3478-
private static final String CURSOR_FIELD = "cursor";
3479-
private static final String RESULT_FIELD = "result";
3480-
private static final String BATCH_SIZE_FIELD = "batchSize";
3481-
private static final String FIRST_BATCH = "firstBatch";
3482-
private static final String NEXT_BATCH = "nextBatch";
3483-
private static final String SERVER_USED = "serverUsed";
3484-
private static final String OK = "ok";
3485-
3486-
private final MongoTemplate template;
3487-
private final ReadPreference readPreference;
3488-
private final int batchSize;
3489-
3490-
BatchAggregationLoader(MongoTemplate template, ReadPreference readPreference, int batchSize) {
3491-
3492-
this.template = template;
3493-
this.readPreference = readPreference;
3494-
this.batchSize = batchSize;
3495-
}
3496-
3497-
/**
3498-
* Run aggregation command and fetch all results.
3499-
*/
3500-
Document aggregate(String collectionName, Aggregation aggregation, AggregationOperationContext context) {
3501-
3502-
Document command = prepareAggregationCommand(collectionName, aggregation, context, batchSize);
3503-
3504-
if (LOGGER.isDebugEnabled()) {
3505-
LOGGER.debug("Executing aggregation: {}", serializeToJsonSafely(command));
3506-
}
3507-
3508-
return mergeAggregationResults(aggregateBatched(command, collectionName, batchSize));
3509-
}
3510-
3511-
/**
3512-
* Pre process the aggregation command sent to the server by adding {@code cursor} options to match execution on
3513-
* different server versions.
3514-
*/
3515-
private static Document prepareAggregationCommand(String collectionName, Aggregation aggregation,
3516-
@Nullable AggregationOperationContext context, int batchSize) {
3517-
3518-
AggregationOperationContext rootContext = context == null ? Aggregation.DEFAULT_CONTEXT : context;
3519-
Document command = aggregation.toDocument(collectionName, rootContext);
3520-
3521-
if (!aggregation.getOptions().isExplain()) {
3522-
command.put(CURSOR_FIELD, new Document(BATCH_SIZE_FIELD, batchSize));
3523-
}
3524-
3525-
return command;
3526-
}
3527-
3528-
private List<Document> aggregateBatched(Document command, String collectionName, int batchSize) {
3529-
3530-
List<Document> results = new ArrayList<>();
3531-
3532-
Document commandResult = template.executeCommand(command, readPreference);
3533-
results.add(postProcessResult(commandResult));
3534-
3535-
while (hasNext(commandResult)) {
3536-
3537-
Document getMore = new Document("getMore", getNextBatchId(commandResult)) //
3538-
.append("collection", collectionName) //
3539-
.append(BATCH_SIZE_FIELD, batchSize);
3540-
3541-
commandResult = template.executeCommand(getMore, this.readPreference);
3542-
results.add(postProcessResult(commandResult));
3543-
}
3544-
3545-
return results;
3546-
}
3547-
3548-
private static Document postProcessResult(Document commandResult) {
3549-
3550-
if (!commandResult.containsKey(CURSOR_FIELD)) {
3551-
return commandResult;
3552-
}
3553-
3554-
Document resultObject = new Document(SERVER_USED, commandResult.get(SERVER_USED));
3555-
resultObject.put(OK, commandResult.get(OK));
3556-
3557-
Document cursor = (Document) commandResult.get(CURSOR_FIELD);
3558-
if (cursor.containsKey(FIRST_BATCH)) {
3559-
resultObject.put(RESULT_FIELD, cursor.get(FIRST_BATCH));
3560-
} else {
3561-
resultObject.put(RESULT_FIELD, cursor.get(NEXT_BATCH));
3562-
}
3563-
3564-
return resultObject;
3565-
}
3566-
3567-
private static Document mergeAggregationResults(List<Document> batchResults) {
3568-
3569-
if (batchResults.size() == 1) {
3570-
return batchResults.iterator().next();
3571-
}
3572-
3573-
Document commandResult = new Document();
3574-
List<Object> allResults = new ArrayList<>();
3575-
3576-
for (Document batchResult : batchResults) {
3577-
3578-
Collection documents = (Collection<?>) batchResult.get(RESULT_FIELD);
3579-
if (!CollectionUtils.isEmpty(documents)) {
3580-
allResults.addAll(documents);
3581-
}
3582-
}
3583-
3584-
// take general info from first batch
3585-
commandResult.put(SERVER_USED, batchResults.iterator().next().get(SERVER_USED));
3586-
commandResult.put(OK, batchResults.iterator().next().get(OK));
3587-
3588-
// and append the merged batchResults
3589-
commandResult.put(RESULT_FIELD, allResults);
3590-
3591-
return commandResult;
3592-
}
3593-
3594-
private static boolean hasNext(Document commandResult) {
3595-
3596-
if (!commandResult.containsKey(CURSOR_FIELD)) {
3597-
return false;
3598-
}
3599-
3600-
Object next = getNextBatchId(commandResult);
3601-
return next != null && ((Number) next).longValue() != 0L;
3602-
}
3603-
3604-
@Nullable
3605-
private static Object getNextBatchId(Document commandResult) {
3606-
return ((Document) commandResult.get(CURSOR_FIELD)).get("id");
3607-
}
3608-
}
3609-
36103476
/**
36113477
* {@link MongoTemplate} extension bound to a specific {@link ClientSession} that is applied when interacting with the
36123478
* server through the driver API.

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@
116116
import org.springframework.util.ResourceUtils;
117117
import org.springframework.util.StringUtils;
118118

119-
import com.mongodb.BasicDBObject;
120119
import com.mongodb.ClientSessionOptions;
121120
import com.mongodb.CursorType;
122121
import com.mongodb.DBCollection;
@@ -3237,25 +3236,34 @@ public <T> FindPublisher<T> prepare(FindPublisher<T> findPublisher) {
32373236
Document sort = type != null ? getMappedSortObject(query, type) : query.getSortObject();
32383237
findPublisherToUse = findPublisherToUse.sort(sort);
32393238
}
3240-
BasicDBObject modifiers = new BasicDBObject();
32413239

32423240
if (StringUtils.hasText(query.getHint())) {
3243-
modifiers.append("$hint", query.getHint());
3241+
findPublisherToUse = findPublisherToUse.hint(Document.parse(query.getHint()));
32443242
}
32453243

32463244
if (meta.hasValues()) {
3247-
for (Entry<String, Object> entry : meta.values()) {
3248-
modifiers.append(entry.getKey(), entry.getValue());
3245+
3246+
if (StringUtils.hasText(meta.getComment())) {
3247+
findPublisherToUse = findPublisherToUse.comment(meta.getComment());
3248+
}
3249+
3250+
if (meta.getSnapshot()) {
3251+
findPublisherToUse = findPublisherToUse.snapshot(meta.getSnapshot());
3252+
}
3253+
3254+
if (meta.getMaxScan() != null) {
3255+
findPublisherToUse = findPublisherToUse.maxScan(meta.getMaxScan());
3256+
}
3257+
3258+
if (meta.getMaxTimeMsec() != null) {
3259+
findPublisherToUse = findPublisherToUse.maxTime(meta.getMaxTimeMsec(), TimeUnit.MILLISECONDS);
32493260
}
32503261

32513262
if (meta.getCursorBatchSize() != null) {
32523263
findPublisherToUse = findPublisherToUse.batchSize(meta.getCursorBatchSize());
32533264
}
32543265
}
32553266

3256-
if (!modifiers.isEmpty()) {
3257-
findPublisherToUse = findPublisherToUse.modifiers(modifiers);
3258-
}
32593267
} catch (RuntimeException e) {
32603268
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
32613269
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoExampleMapper.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,14 @@ private void applyPropertySpecs(String path, Document source, Class<?> probeType
164164
if (exampleSpecAccessor.hasPropertySpecifier(mappedPropertyPath)) {
165165

166166
PropertyValueTransformer valueTransformer = exampleSpecAccessor.getValueTransformerForPath(mappedPropertyPath);
167-
value = valueTransformer.convert(value);
168-
if (value == null) {
167+
Optional converted = valueTransformer.apply(Optional.ofNullable(value));
168+
169+
if(!converted.isPresent()) {
169170
iter.remove();
170171
continue;
171172
}
172173

173-
entry.setValue(value);
174+
entry.setValue(converted.get());
174175
}
175176

176177
if (entry.getValue() instanceof String) {

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Meta.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.mongodb.core.query;
1717

18+
import java.time.Duration;
1819
import java.util.Collections;
1920
import java.util.LinkedHashMap;
2021
import java.util.LinkedHashSet;
@@ -66,19 +67,33 @@ public Long getMaxTimeMsec() {
6667
* @param maxTimeMsec
6768
*/
6869
public void setMaxTimeMsec(long maxTimeMsec) {
69-
setMaxTime(maxTimeMsec, TimeUnit.MILLISECONDS);
70+
setMaxTime(Duration.ofMillis(maxTimeMsec));
7071
}
7172

7273
/**
7374
* Set the maximum time limit for processing operations.
7475
*
7576
* @param timeout
7677
* @param timeUnit
78+
* @deprecated since 2.1. Use {@link #setMaxTime(Duration)} instead.
7779
*/
80+
@Deprecated
7881
public void setMaxTime(long timeout, @Nullable TimeUnit timeUnit) {
7982
setValue(MetaKey.MAX_TIME_MS.key, (timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS).toMillis(timeout));
8083
}
8184

85+
/**
86+
* Set the maximum time limit for processing operations.
87+
*
88+
* @param timeout must not be {@literal null}.
89+
* @since 2.1
90+
*/
91+
public void setMaxTime(Duration timeout) {
92+
93+
Assert.notNull(timeout, "Timeout must not be null!");
94+
setValue(MetaKey.MAX_TIME_MS.key, timeout.toMillis());
95+
}
96+
8297
/**
8398
* @return {@literal null} if not set.
8499
*/
@@ -91,13 +106,15 @@ public Long getMaxScan() {
91106
* Only scan the specified number of documents.
92107
*
93108
* @param maxScan
109+
* @deprecated since 2.1 due to deprecation in MongoDB 4.0.
94110
*/
111+
@Deprecated
95112
public void setMaxScan(long maxScan) {
96113
setValue(MetaKey.MAX_SCAN.key, maxScan);
97114
}
98115

99116
/**
100-
* Add a comment to the query.
117+
* Add a comment to the query that is propagated to the profile log.
101118
*
102119
* @param comment
103120
*/
@@ -117,7 +134,9 @@ public String getComment() {
117134
* Using snapshot prevents the cursor from returning a document more than once.
118135
*
119136
* @param useSnapshot
137+
* @deprecated since 2.1 due to deprecation as of MongoDB 3.6
120138
*/
139+
@Deprecated
121140
public void setSnapshot(boolean useSnapshot) {
122141
setValue(MetaKey.SNAPSHOT.key, useSnapshot);
123142
}
@@ -139,9 +158,11 @@ public Integer getCursorBatchSize() {
139158
}
140159

141160
/**
142-
* Apply the batch size for a query.
161+
* Apply the batch size (number of documents to return in each response) for a query. <br />
162+
* Use {@literal 0 (zero)} for no limit. A <strong>negative limit</strong> closes the cursor after returning a single
163+
* batch indicating to the server that the client will not ask for a subsequent one.
143164
*
144-
* @param cursorBatchSize
165+
* @param cursorBatchSize The number of documents to return per batch.
145166
* @since 2.1
146167
*/
147168
public void setCursorBatchSize(int cursorBatchSize) {

0 commit comments

Comments
 (0)