Skip to content

Commit 48911f0

Browse files
Polishing.
Original Pull Request: #4960
1 parent e2d371a commit 48911f0

22 files changed

+431
-254
lines changed

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

+10-17
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ protected <T> Stream<T> doStream(Query query, Class<?> entityType, String collec
486486
return doStream(query, entityType, collectionName, returnType, QueryResultConverter.entity());
487487
}
488488

489-
@SuppressWarnings("ConstantConditions")
489+
@SuppressWarnings({"ConstantConditions", "NullAway"})
490490
<T, R> Stream<R> doStream(Query query, Class<?> entityType, String collectionName, Class<T> returnType,
491491
QueryResultConverter<? super T, ? extends R> resultConverter) {
492492

@@ -1086,34 +1086,29 @@ <T, R> GeoResults<R> doGeoNear(NearQuery near, Class<?> domainType, String colle
10861086
return new GeoResults<>(result, avgDistance);
10871087
}
10881088

1089-
@Nullable
1090-
@Override
1091-
public <T> T findAndModify(Query query, UpdateDefinition update, Class<T> entityClass) {
1089+
public <T> @Nullable T findAndModify(Query query, UpdateDefinition update, Class<T> entityClass) {
10921090
return findAndModify(query, update, new FindAndModifyOptions(), entityClass, getCollectionName(entityClass));
10931091
}
10941092

1095-
@Nullable
10961093
@Override
1097-
public <T> T findAndModify(Query query, UpdateDefinition update, Class<T> entityClass,
1094+
public <T> @Nullable T findAndModify(Query query, UpdateDefinition update, Class<T> entityClass,
10981095
String collectionName) {
10991096
return findAndModify(query, update, new FindAndModifyOptions(), entityClass, collectionName);
11001097
}
11011098

1102-
@Nullable
11031099
@Override
1104-
public <T> T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options,
1100+
public <T> @Nullable T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options,
11051101
Class<T> entityClass) {
11061102
return findAndModify(query, update, options, entityClass, getCollectionName(entityClass));
11071103
}
11081104

1109-
@Nullable
11101105
@Override
1111-
public <T> T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options,
1106+
public <T> @Nullable T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options,
11121107
Class<T> entityClass, String collectionName) {
11131108
return findAndModify(query, update, options, entityClass, collectionName, QueryResultConverter.entity());
11141109
}
11151110

1116-
<S, T> T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options,
1111+
<S, T> @Nullable T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options,
11171112
Class<S> entityClass, String collectionName, QueryResultConverter<? super S, ? extends T> resultConverter) {
11181113

11191114
Assert.notNull(query, "Query must not be null");
@@ -1185,15 +1180,13 @@ <S, T> T findAndModify(Query query, UpdateDefinition update, FindAndModifyOption
11851180
// Find methods that take a Query to express the query and that return a single object that is also removed from the
11861181
// collection in the database.
11871182

1188-
@Nullable
11891183
@Override
1190-
public <T> T findAndRemove(Query query, Class<T> entityClass) {
1184+
public <T> @Nullable T findAndRemove(Query query, Class<T> entityClass) {
11911185
return findAndRemove(query, entityClass, getCollectionName(entityClass));
11921186
}
11931187

1194-
@Nullable
11951188
@Override
1196-
public <T> T findAndRemove(Query query, Class<T> entityClass, String collectionName) {
1189+
public <T> @Nullable T findAndRemove(Query query, Class<T> entityClass, String collectionName) {
11971190

11981191
Assert.notNull(query, "Query must not be null");
11991192
Assert.notNull(entityClass, "EntityClass must not be null");
@@ -2161,11 +2154,11 @@ protected <S, T> UpdateResult replace(Query query, Class<S> entityType, T replac
21612154
* @param entityClass
21622155
* @return
21632156
*/
2164-
@SuppressWarnings("NullAway")
21652157
protected <T> List<T> doFindAndDelete(String collectionName, Query query, Class<T> entityClass) {
21662158
return doFindAndDelete(collectionName, query, entityClass, QueryResultConverter.entity());
21672159
}
21682160

2161+
@SuppressWarnings("NullAway")
21692162
<S, T> List<T> doFindAndDelete(String collectionName, Query query, Class<S> entityClass,
21702163
QueryResultConverter<? super S, ? extends T> resultConverter) {
21712164

@@ -2229,7 +2222,7 @@ protected <O> AggregationResults<O> doAggregate(Aggregation aggregation, String
22292222
return doAggregate(aggregation, collectionName, outputType, QueryResultConverter.entity(), context);
22302223
}
22312224

2232-
@SuppressWarnings("ConstantConditions")
2225+
@SuppressWarnings({"ConstantConditions", "NullAway"})
22332226
<T, O> AggregationResults<O> doAggregate(Aggregation aggregation, String collectionName, Class<T> outputType,
22342227
QueryResultConverter<? super T, ? extends O> resultConverter, AggregationOperationContext context) {
22352228

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

+1
Original file line numberDiff line numberDiff line change
@@ -2293,6 +2293,7 @@ protected <T> Flux<T> doFindAndDelete(String collectionName, Query query, Class<
22932293
.flatMapSequential(deleteResult -> Flux.fromIterable(list)));
22942294
}
22952295

2296+
@SuppressWarnings({"rawtypes", "unchecked", "NullAway"})
22962297
<S, T> Flux<T> doFindAndDelete(String collectionName, Query query, Class<S> entityClass,
22972298
QueryResultConverter<? super S, ? extends T> resultConverter) {
22982299

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

+12-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
import java.util.function.Predicate;
2323

2424
import org.bson.Document;
25+
import org.jspecify.annotations.Nullable;
2526
import org.springframework.lang.Contract;
2627
import org.springframework.util.Assert;
28+
import org.springframework.util.CollectionUtils;
2729

2830
/**
2931
* The {@link AggregationPipeline} holds the collection of {@link AggregationOperation aggregation stages}.
@@ -82,6 +84,14 @@ public List<AggregationOperation> getOperations() {
8284
return Collections.unmodifiableList(pipeline);
8385
}
8486

87+
public @Nullable AggregationOperation firstOperation() {
88+
return CollectionUtils.firstElement(pipeline);
89+
}
90+
91+
public @Nullable AggregationOperation lastOperation() {
92+
return CollectionUtils.lastElement(pipeline);
93+
}
94+
8595
List<Document> toDocuments(AggregationOperationContext context) {
8696

8797
verify();
@@ -97,8 +107,8 @@ public boolean isOutOrMerge() {
97107
return false;
98108
}
99109

100-
AggregationOperation operation = pipeline.get(pipeline.size() - 1);
101-
return isOut(operation) || isMerge(operation);
110+
AggregationOperation operation = lastOperation();
111+
return operation != null && (isOut(operation) || isMerge(operation));
102112
}
103113

104114
void verify() {

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

+1
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ public SortArray sort(Sort sort) {
356356
* @return new instance of {@link SortArray}.
357357
* @since 4.5
358358
*/
359+
@SuppressWarnings("NullAway")
359360
public SortArray sort(Direction direction) {
360361

361362
if (usesFieldRef()) {

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,10 @@ public Document toDocument(AggregationOperationContext context) {
237237
}
238238

239239
$vectorSearch.append("index", indexName);
240-
$vectorSearch.append("limit", limit.max());
240+
241+
if(limit.isLimited()) { // TODO: exception or pass it on?
242+
$vectorSearch.append("limit", limit.max());
243+
}
241244

242245
if (numCandidates != null) {
243246
$vectorSearch.append("numCandidates", numCandidates);

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public PotentiallyConvertingIterator iterator() {
7777
}
7878

7979
@Override
80-
public Vector getVector() {
80+
public @Nullable Vector getVector() {
8181
return delegate.getVector();
8282
}
8383

@@ -104,12 +104,12 @@ public Sort getSort() {
104104
}
105105

106106
@Override
107-
public @org.jspecify.annotations.Nullable Score getScore() {
107+
public @Nullable Score getScore() {
108108
return delegate.getScore();
109109
}
110110

111111
@Override
112-
public @org.jspecify.annotations.Nullable Range<Score> getScoreRange() {
112+
public @Nullable Range<Score> getScoreRange() {
113113
return delegate.getScoreRange();
114114
}
115115

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessor.java

+4-5
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,13 @@ public MongoParametersParameterAccessor(MongoQueryMethod method, Object[] values
6161
public Range<Score> getScoreRange() {
6262

6363
MongoParameters mongoParameters = method.getParameters();
64-
int rangeIndex = mongoParameters.getScoreRangeIndex();
6564

66-
if (rangeIndex != -1) {
67-
return getValue(rangeIndex);
65+
if (mongoParameters.hasScoreRangeParameter()) {
66+
return getValue(mongoParameters.getScoreRangeIndex());
6867
}
6968

70-
int scoreIndex = mongoParameters.getScoreIndex();
71-
Bound<Score> maxDistance = scoreIndex == -1 ? Bound.unbounded() : Bound.inclusive((Score) getScore());
69+
Score score = getScore();
70+
Bound<Score> maxDistance = score != null ? Bound.inclusive(score) : Bound.unbounded();
7271

7372
return Range.of(Bound.unbounded(), maxDistance);
7473
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java

+27-22
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
*/
1616
package org.springframework.data.mongodb.repository.query;
1717

18-
import static org.springframework.data.mongodb.core.query.Criteria.*;
18+
import static org.springframework.data.mongodb.core.query.Criteria.Placeholder;
19+
import static org.springframework.data.mongodb.core.query.Criteria.where;
1920

2021
import java.util.Arrays;
2122
import java.util.Collection;
@@ -27,7 +28,6 @@
2728
import org.apache.commons.logging.LogFactory;
2829
import org.bson.BsonRegularExpression;
2930
import org.jspecify.annotations.Nullable;
30-
3131
import org.springframework.data.domain.Range;
3232
import org.springframework.data.domain.Range.Bound;
3333
import org.springframework.data.domain.Sort;
@@ -118,8 +118,9 @@ protected Criteria create(Part part, Iterator<Object> iterator) {
118118
return new Criteria();
119119
}
120120

121-
if (isSearchQuery && (part.getType().equals(Type.NEAR) || part.getType().equals(Type.WITHIN))) {
122-
return null;
121+
if (isPartOfSearchQuery(part)) {
122+
skip(part, iterator);
123+
return new Criteria();
123124
}
124125

125126
PersistentPropertyPath<MongoPersistentProperty> path = context.getPersistentPropertyPath(part.getProperty());
@@ -135,7 +136,8 @@ protected Criteria and(Part part, Criteria base, Iterator<Object> iterator) {
135136
return create(part, iterator);
136137
}
137138

138-
if (isSearchQuery && (part.getType().equals(Type.NEAR) || part.getType().equals(Type.WITHIN))) {
139+
if (isPartOfSearchQuery(part)) {
140+
skip(part, iterator);
139141
return base;
140142
}
141143

@@ -176,15 +178,6 @@ protected Query complete(@Nullable Criteria criteria, Sort sort) {
176178
@SuppressWarnings("NullAway")
177179
private Criteria from(Part part, MongoPersistentProperty property, Criteria criteria, Iterator<Object> parameters) {
178180

179-
if (isSearchQuery && (part.getType().equals(Type.NEAR) || part.getType().equals(Type.WITHIN))) {
180-
181-
int numberOfArguments = part.getType().getNumberOfArguments();
182-
for (int i = 0; i < numberOfArguments; i++) {
183-
parameters.next();
184-
}
185-
return null;
186-
}
187-
188181
Type type = part.getType();
189182

190183
switch (type) {
@@ -206,13 +199,13 @@ private Criteria from(Part part, MongoPersistentProperty property, Criteria crit
206199
return criteria.is(null);
207200
case NOT_IN:
208201
Object ninValue = parameters.next();
209-
if(ninValue instanceof Placeholder) {
202+
if (ninValue instanceof Placeholder) {
210203
return criteria.raw("$nin", ninValue);
211204
}
212205
return criteria.nin(valueAsList(ninValue, part));
213206
case IN:
214207
Object inValue = parameters.next();
215-
if(inValue instanceof Placeholder) {
208+
if (inValue instanceof Placeholder) {
216209
return criteria.raw("$in", inValue);
217210
}
218211
return criteria.in(valueAsList(inValue, part));
@@ -231,7 +224,7 @@ private Criteria from(Part part, MongoPersistentProperty property, Criteria crit
231224
return param instanceof Pattern pattern ? criteria.regex(pattern) : criteria.regex(param.toString());
232225
case EXISTS:
233226
Object next = parameters.next();
234-
if(next instanceof Placeholder placeholder) {
227+
if (next instanceof Placeholder placeholder) {
235228
return criteria.raw("$exists", placeholder);
236229
} else {
237230
return criteria.exists((Boolean) next);
@@ -355,7 +348,7 @@ private Criteria createContainingCriteria(Part part, MongoPersistentProperty pro
355348

356349
if (property.isCollectionLike()) {
357350
Object next = parameters.next();
358-
if(next instanceof Placeholder) {
351+
if (next instanceof Placeholder) {
359352
return criteria.raw("$in", next);
360353
}
361354
return criteria.in(valueAsList(next, part));
@@ -433,8 +426,7 @@ private java.util.List<?> valueAsList(Object value, Part part) {
433426
streamable = streamable.map(it -> {
434427
if (it instanceof String sv) {
435428

436-
return new BsonRegularExpression(MongoRegexCreator.INSTANCE.toRegularExpression(sv, matchMode),
437-
regexOptions);
429+
return new BsonRegularExpression(MongoRegexCreator.INSTANCE.toRegularExpression(sv, matchMode), regexOptions);
438430
}
439431
return it;
440432
});
@@ -468,10 +460,23 @@ private boolean isSpherical(MongoPersistentProperty property) {
468460
return false;
469461
}
470462

463+
private boolean isPartOfSearchQuery(Part part) {
464+
return isSearchQuery && (part.getType().equals(Type.NEAR) || part.getType().equals(Type.WITHIN));
465+
}
466+
467+
private static void skip(Part part, Iterator<?> parameters) {
468+
469+
int total = part.getNumberOfArguments();
470+
int i = 0;
471+
while (parameters.hasNext() && i < total) {
472+
parameters.next();
473+
i++;
474+
}
475+
}
476+
471477
/**
472478
* Compute a {@link Type#BETWEEN} typed {@link Part} using {@link Criteria#gt(Object) $gt},
473-
* {@link Criteria#gte(Object) $gte}, {@link Criteria#lt(Object) $lt} and {@link Criteria#lte(Object) $lte}.
474-
* <br />
479+
* {@link Criteria#gte(Object) $gte}, {@link Criteria#lt(Object) $lt} and {@link Criteria#lte(Object) $lte}. <br />
475480
* In case the first {@literal value} is actually a {@link Range} the lower and upper bounds of the {@link Range} are
476481
* used according to their {@link Bound#isInclusive() inclusion} definition. Otherwise the {@literal value} is used
477482
* for {@literal $gt} and {@link Iterator#next() parameters.next()} as {@literal $lt}.

0 commit comments

Comments
 (0)