Skip to content

Commit a53ea25

Browse files
committed
Polishing.
Remove Field type. Refactor container to subclass MongoDBAtlasLocalContainer. Introduce wait/synchronization to avoid container crashes on create index + list search indexes. See #4706 Original pull request: #4882
1 parent 2d7d7bf commit a53ea25

16 files changed

+189
-269
lines changed

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ private JsonSchemaProperty computeSchemaForProperty(List<MongoPersistentProperty
185185
Class<?> rawTargetType = computeTargetType(property); // target type before conversion
186186
Class<?> targetType = converter.getTypeMapper().getWriteTargetTypeFor(rawTargetType); // conversion target type
187187

188-
if((rawTargetType.isPrimitive() || ClassUtils.isPrimitiveArray(rawTargetType)) && targetType == Object.class) {
188+
if ((rawTargetType.isPrimitive() || ClassUtils.isPrimitiveArray(rawTargetType)) && targetType == Object.class) {
189189
targetType = rawTargetType;
190190
}
191191

@@ -338,8 +338,8 @@ private TypedJsonSchemaObject createSchemaObject(Object type, Collection<?> poss
338338

339339
private String computePropertyFieldName(PersistentProperty<?> property) {
340340

341-
return property instanceof MongoPersistentProperty mongoPersistentProperty ?
342-
mongoPersistentProperty.getFieldName() : property.getName();
341+
return property instanceof MongoPersistentProperty mongoPersistentProperty ? mongoPersistentProperty.getFieldName()
342+
: property.getName();
343343
}
344344

345345
private boolean isRequiredProperty(PersistentProperty<?> property) {

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

+33-52
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,14 @@
1616
package org.springframework.data.mongodb.core.aggregation;
1717

1818
import java.util.Arrays;
19-
import java.util.LinkedHashSet;
2019
import java.util.List;
21-
import java.util.Map;
2220
import java.util.Set;
2321
import java.util.function.Consumer;
2422
import java.util.stream.Collectors;
2523

2624
import org.bson.BinaryVector;
2725
import org.bson.Document;
26+
2827
import org.springframework.data.domain.Limit;
2928
import org.springframework.data.domain.Vector;
3029
import org.springframework.data.mongodb.core.mapping.MongoVector;
@@ -177,7 +176,7 @@ public String getKey() {
177176
* can't specify a number less than the number of documents to return (limit). This field is required if
178177
* {@link #searchType(SearchType)} is {@link SearchType#ANN} or {@link SearchType#DEFAULT}.
179178
*
180-
* @param numCandidates
179+
* @param numCandidates number of nearest neighbors to use during the search
181180
* @return a new {@link VectorSearchOperation} with {@code numCandidates} applied.
182181
*/
183182
@Contract("_ -> new")
@@ -338,20 +337,25 @@ public enum SearchType {
338337
ENN
339338
}
340339

341-
// A query path cannot only contain the name of the filed but may also hold additional information about the
342-
// analyzer to use;
343-
// "path": [ "names", "notes", { "value": "comments", "multi": "mySecondaryAnalyzer" } ]
344-
// see: https://www.mongodb.com/docs/atlas/atlas-search/path-construction/#std-label-ref-path
340+
/**
341+
* Value object capturing query paths.
342+
*/
345343
public static class QueryPaths {
346344

347-
Set<QueryPath<?>> paths;
345+
private final Set<QueryPath<?>> paths;
348346

349-
public static QueryPaths of(QueryPath<String> path) {
347+
private QueryPaths(Set<QueryPath<?>> paths) {
348+
this.paths = paths;
349+
}
350350

351-
QueryPaths queryPaths = new QueryPaths();
352-
queryPaths.paths = new LinkedHashSet<>(2);
353-
queryPaths.paths.add(path);
354-
return queryPaths;
351+
/**
352+
* Factory method to create {@link QueryPaths} from a single {@link QueryPath}.
353+
*
354+
* @param path
355+
* @return a new {@link QueryPaths} instance.
356+
*/
357+
public static QueryPaths of(QueryPath<String> path) {
358+
return new QueryPaths(Set.of(path));
355359
}
356360

357361
Object getPathObject() {
@@ -363,21 +367,19 @@ Object getPathObject() {
363367
}
364368
}
365369

370+
/**
371+
* Interface describing a query path contract. Query paths might be simple field names, wildcard paths, or
372+
* multi-paths. paths.
373+
*
374+
* @param <T>
375+
*/
366376
public interface QueryPath<T> {
367377

368378
T value();
369379

370380
static QueryPath<String> path(String field) {
371381
return new SimplePath(field);
372382
}
373-
374-
static QueryPath<Map<String, Object>> wildcard(String field) {
375-
return new WildcardPath(field);
376-
}
377-
378-
static QueryPath<Map<String, Object>> multi(String field, String analyzer) {
379-
return new MultiPath(field, analyzer);
380-
}
381383
}
382384

383385
public static class SimplePath implements QueryPath<String> {
@@ -394,36 +396,9 @@ public String value() {
394396
}
395397
}
396398

397-
public static class WildcardPath implements QueryPath<Map<String, Object>> {
398-
399-
String name;
400-
401-
public WildcardPath(String name) {
402-
this.name = name;
403-
}
404-
405-
@Override
406-
public Map<String, Object> value() {
407-
return Map.of("wildcard", name);
408-
}
409-
}
410-
411-
public static class MultiPath implements QueryPath<Map<String, Object>> {
412-
413-
String field;
414-
String analyzer;
415-
416-
public MultiPath(String field, String analyzer) {
417-
this.field = field;
418-
this.analyzer = analyzer;
419-
}
420-
421-
@Override
422-
public Map<String, Object> value() {
423-
return Map.of("value", field, "multi", analyzer);
424-
}
425-
}
426-
399+
/**
400+
* Fluent API to configure a path on the VectorSearchOperation builder.
401+
*/
427402
public interface PathContributor {
428403

429404
/**
@@ -436,6 +411,9 @@ public interface PathContributor {
436411
VectorContributor path(String path);
437412
}
438413

414+
/**
415+
* Fluent API to configure a vector on the VectorSearchOperation builder.
416+
*/
439417
public interface VectorContributor {
440418

441419
/**
@@ -458,7 +436,7 @@ default LimitContributor vector(float... vector) {
458436
* @return
459437
*/
460438
@Contract("_ -> this")
461-
default LimitContributor vector(byte... vector) {
439+
default LimitContributor vector(byte[] vector) {
462440
return vector(BinaryVector.int8Vector(vector));
463441
}
464442

@@ -510,6 +488,9 @@ default LimitContributor vector(BinaryVector vector) {
510488
LimitContributor vector(Vector vector);
511489
}
512490

491+
/**
492+
* Fluent API to configure a limit on the VectorSearchOperation builder.
493+
*/
513494
public interface LimitContributor {
514495

515496
/**

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

+2-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package org.springframework.data.mongodb.core.convert;
1717

18-
import static org.springframework.data.convert.ConverterBuilder.reading;
18+
import static org.springframework.data.convert.ConverterBuilder.*;
1919

2020
import java.math.BigDecimal;
2121
import java.math.BigInteger;
@@ -47,6 +47,7 @@
4747
import org.bson.types.Code;
4848
import org.bson.types.Decimal128;
4949
import org.bson.types.ObjectId;
50+
5051
import org.springframework.core.convert.ConversionFailedException;
5152
import org.springframework.core.convert.TypeDescriptor;
5253
import org.springframework.core.convert.converter.ConditionalConverter;
@@ -118,8 +119,6 @@ static Collection<Object> getConvertersToRegister() {
118119
converters.add(reading(BsonUndefined.class, Object.class, it -> null));
119120
converters.add(reading(String.class, URI.class, URI::create).andWriting(URI::toString));
120121

121-
converters.add(ByteArrayConverterFactory.INSTANCE);
122-
123122
return converters;
124123
}
125124

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ public interface IndexOperations {
3333
*
3434
* @param indexDefinition must not be {@literal null}.
3535
* @return the index name.
36-
* @deprecated in favor of {@link #createIndex(IndexDefinition)}.
36+
* @deprecated since 4.5, in favor of {@link #createIndex(IndexDefinition)}.
3737
*/
3838
@Deprecated(since = "4.5", forRemoval = true)
3939
String ensureIndex(IndexDefinition indexDefinition);
4040

4141
/**
42-
* Create the index for the provided {@link IndexDefinition} exists for the collection indicated by the entity
43-
* class. If not it will be created.
42+
* Create the index for the provided {@link IndexDefinition} exists for the collection indicated by the entity class.
43+
* If not it will be created.
4444
*
4545
* @param indexDefinition must not be {@literal null}.
4646
* @return the index name.

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

+14
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,23 @@ public interface ReactiveIndexOperations {
3333
*
3434
* @param indexDefinition must not be {@literal null}.
3535
* @return a {@link Mono} emitting the name of the index on completion.
36+
* @deprecated since 4.5, in favor of {@link #createIndex(IndexDefinition)}.
3637
*/
38+
@Deprecated(since = "4.5", forRemoval = true)
3739
Mono<String> ensureIndex(IndexDefinition indexDefinition);
3840

41+
/**
42+
* Create the index for the provided {@link IndexDefinition} exists for the collection indicated by the entity class.
43+
* If not it will be created.
44+
*
45+
* @param indexDefinition must not be {@literal null}.
46+
* @return the index name.
47+
* @since 4.5
48+
*/
49+
default Mono<String> createIndex(IndexDefinition indexDefinition) {
50+
return ensureIndex(indexDefinition);
51+
}
52+
3953
/**
4054
* Alters the index with given {@literal name}.
4155
*

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public interface SearchIndexDefinition {
4545
* Returns the index document for this index without any potential entity context resolving field name mappings. The
4646
* resulting document contains the index name, type and {@link #getDefinition(TypeInformation, MappingContext)
4747
* definition}.
48-
*
48+
*
4949
* @return never {@literal null}.
5050
*/
5151
default Document getRawIndexDocument() {
@@ -74,12 +74,14 @@ default Document getIndexDocument(@Nullable TypeInformation<?> entity,
7474

7575
/**
7676
* Returns the actual index definition for this index in the context of a potential entity to resolve field name
77-
* mappings.
77+
* mappings. Entity and context can be {@literal null} to create a generic index definition without applying field
78+
* name mapping.
7879
*
7980
* @param entity can be {@literal null}.
80-
* @param mappingContext
81+
* @param mappingContext can be {@literal null}.
8182
* @return never {@literal null}.
8283
*/
8384
Document getDefinition(@Nullable TypeInformation<?> entity,
8485
@Nullable MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext);
86+
8587
}

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

+16-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@
2727

2828
/**
2929
* Index information for a MongoDB Search Index.
30-
*
30+
*
3131
* @author Christoph Strobl
32+
* @since 4.5
3233
*/
3334
public class SearchIndexInfo {
3435

@@ -42,14 +43,27 @@ public class SearchIndexInfo {
4243
this.indexDefinition = Lazy.of(indexDefinition);
4344
}
4445

46+
/**
47+
* Parse a BSON document describing an index into a {@link SearchIndexInfo}.
48+
*
49+
* @param source BSON document describing the index.
50+
* @return a new {@link SearchIndexInfo} instance.
51+
*/
4552
public static SearchIndexInfo parse(String source) {
4653
return of(Document.parse(source));
4754
}
4855

56+
/**
57+
* Create an index from its BSON {@link Document} representation into a {@link SearchIndexInfo}.
58+
*
59+
* @param indexDocument BSON document describing the index.
60+
* @return a new {@link SearchIndexInfo} instance.
61+
*/
4962
public static SearchIndexInfo of(Document indexDocument) {
5063

5164
Object id = indexDocument.get("id");
52-
SearchIndexStatus status = SearchIndexStatus.valueOf(indexDocument.get("status", "DOES_NOT_EXIST"));
65+
SearchIndexStatus status = SearchIndexStatus
66+
.valueOf(indexDocument.get("status", SearchIndexStatus.DOES_NOT_EXIST.name()));
5367

5468
return new SearchIndexInfo(id, status, () -> readIndexDefinition(indexDocument));
5569
}

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

-12
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,6 @@
2727
*/
2828
public interface SearchIndexOperations {
2929

30-
/**
31-
* Create the index for the given {@link SearchIndexDefinition} in the collection indicated by the entity class.
32-
*
33-
* @param indexDefinition must not be {@literal null}.
34-
* @return the index name.
35-
*/
36-
// TODO: keep or just go with createIndex?
37-
default String ensureIndex(SearchIndexDefinition indexDefinition) {
38-
return createIndex(indexDefinition);
39-
}
40-
4130
/**
4231
* Create the index for the given {@link SearchIndexDefinition} in the collection indicated by the entity class.
4332
*
@@ -53,7 +42,6 @@ default String ensureIndex(SearchIndexDefinition indexDefinition) {
5342
*
5443
* @param indexDefinition the index definition.
5544
*/
56-
// TODO: keep or remove since it does not work reliably?
5745
void updateIndex(SearchIndexDefinition indexDefinition);
5846

5947
/**

0 commit comments

Comments
 (0)