Skip to content

Commit df38fc1

Browse files
Index resolution
1 parent 4652181 commit df38fc1

File tree

4 files changed

+120
-17
lines changed

4 files changed

+120
-17
lines changed

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,8 @@ private void potentiallyAddIndexForProperty(MongoPersistentEntity<?> root, Mongo
135135

136136
try {
137137
if (persistentProperty.isEntity()) {
138-
indexes.addAll(resolveIndexForClass(persistentProperty.getTypeInformation().getActualType(),
139-
persistentProperty.getFieldName(), Path.of(persistentProperty), root.getCollection(), guard));
138+
indexes.addAll(resolveIndexForEntity(mappingContext.getPersistentEntity(persistentProperty),
139+
persistentProperty.isEmbedded() ? "" : persistentProperty.getFieldName(), Path.of(persistentProperty), root.getCollection(), guard));
140140
}
141141

142142
List<IndexDefinitionHolder> indexDefinitions = createIndexDefinitionHolderForProperty(
@@ -163,7 +163,11 @@ private void potentiallyAddIndexForProperty(MongoPersistentEntity<?> root, Mongo
163163
private List<IndexDefinitionHolder> resolveIndexForClass(final TypeInformation<?> type, final String dotPath,
164164
final Path path, final String collection, final CycleGuard guard) {
165165

166-
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(type);
166+
return resolveIndexForEntity(mappingContext.getRequiredPersistentEntity(type), dotPath, path, collection, guard);
167+
}
168+
169+
private List<IndexDefinitionHolder> resolveIndexForEntity(MongoPersistentEntity<?> entity, final String dotPath,
170+
final Path path, final String collection, final CycleGuard guard) {
167171

168172
final List<IndexDefinitionHolder> indexInformation = new ArrayList<>();
169173
indexInformation.addAll(potentiallyCreateCompoundIndexDefinitions(dotPath, collection, entity));
@@ -179,14 +183,18 @@ private List<IndexDefinitionHolder> resolveIndexForClass(final TypeInformation<?
179183
private void guardAndPotentiallyAddIndexForProperty(MongoPersistentProperty persistentProperty, String dotPath,
180184
Path path, String collection, List<IndexDefinitionHolder> indexes, CycleGuard guard) {
181185

182-
String propertyDotPath = (StringUtils.hasText(dotPath) ? dotPath + "." : "") + persistentProperty.getFieldName();
186+
String propertyDotPath = dotPath;
187+
188+
if(!persistentProperty.isEmbedded()) {
189+
propertyDotPath = (StringUtils.hasText(dotPath) ? dotPath + "." : "") + persistentProperty.getFieldName();
190+
}
183191

184192
Path propertyPath = path.append(persistentProperty);
185193
guard.protect(persistentProperty, propertyPath);
186194

187195
if (persistentProperty.isEntity()) {
188196
try {
189-
indexes.addAll(resolveIndexForClass(persistentProperty.getTypeInformation().getActualType(), propertyDotPath,
197+
indexes.addAll(resolveIndexForEntity(mappingContext.getPersistentEntity(persistentProperty), propertyDotPath,
190198
propertyPath, collection, guard));
191199
} catch (CyclicPropertyReferenceException e) {
192200
LOGGER.info(e.getMessage());

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,9 +2335,41 @@ void readDeepNestedEmbeddedType() {
23352335
assertThat(target.nullableEmbedded.embeddableValue).isEqualTo(embeddableValue);
23362336
}
23372337

2338-
@Test
2339-
void xxx() {
2340-
fail("TODO: embedded with complex types");
2338+
@Test // DATAMONGO-1902
2339+
void readEmbeddedTypeWithComplexValue() {
2340+
2341+
org.bson.Document source = new org.bson.Document("_id", "id-1").append("address",
2342+
new org.bson.Document("street", "1007 Mountain Drive").append("city", "Gotham"));
2343+
2344+
WithNullableEmbedded target = converter.read(WithNullableEmbedded.class, source);
2345+
2346+
Address expected = new Address();
2347+
expected.city = "Gotham";
2348+
expected.street = "1007 Mountain Drive";
2349+
2350+
assertThat(target.embeddableValue.address) //
2351+
.isEqualTo(expected);
2352+
}
2353+
2354+
@Test // DATAMONGO-1902
2355+
void writeEmbeddedTypeWithComplexValue() {
2356+
2357+
WithNullableEmbedded source = new WithNullableEmbedded();
2358+
source.id = "id-1";
2359+
source.embeddableValue = new EmbeddableType();
2360+
source.embeddableValue.address = new Address();
2361+
source.embeddableValue.address.city = "Gotham";
2362+
source.embeddableValue.address.street = "1007 Mountain Drive";
2363+
2364+
org.bson.Document target = new org.bson.Document();
2365+
converter.write(source, target);
2366+
2367+
assertThat(target) //
2368+
.containsEntry("address", new org.bson.Document("street", "1007 Mountain Drive").append("city", "Gotham")) //
2369+
.doesNotContainKey("street") //
2370+
.doesNotContainKey("address.street") //
2371+
.doesNotContainKey("city") //
2372+
.doesNotContainKey("address.city");
23412373
}
23422374

23432375
static class GenericType<T> {
@@ -2369,6 +2401,7 @@ interface InterfaceType {
23692401

23702402
}
23712403

2404+
@EqualsAndHashCode
23722405
static class Address implements InterfaceType {
23732406
String street;
23742407
String city;
@@ -2842,6 +2875,8 @@ static class EmbeddableType {
28422875

28432876
@Transient //
28442877
String transientValue;
2878+
2879+
Address address;
28452880
}
28462881

28472882
static class ReturningAfterConvertCallback implements AfterConvertCallback<Person> {

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoExampleMapperUnitTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import org.bson.conversions.Bson;
3030
import org.junit.jupiter.api.BeforeEach;
31+
import org.junit.jupiter.api.Disabled;
3132
import org.junit.jupiter.api.Test;
3233
import org.junit.jupiter.api.extension.ExtendWith;
3334
import org.mockito.Mock;
@@ -454,6 +455,12 @@ public void untypedExampleShouldNotInferTypeRestriction() {
454455
assertThat(document).doesNotContainKey("_class");
455456
}
456457

458+
@Test
459+
@Disabled("TODO: embedded types")
460+
void xxx() {
461+
// TODO: embedded
462+
}
463+
457464
static class FlatDocument {
458465

459466
@Id String id;

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@
2222
import java.lang.annotation.Retention;
2323
import java.lang.annotation.RetentionPolicy;
2424
import java.lang.annotation.Target;
25-
import java.util.Collections;
25+
import java.util.Arrays;
26+
import java.util.LinkedHashSet;
2627
import java.util.List;
2728

2829
import org.junit.Test;
2930
import org.junit.runner.RunWith;
3031
import org.junit.runners.Suite;
3132
import org.junit.runners.Suite.SuiteClasses;
3233
import org.springframework.core.annotation.AliasFor;
34+
import org.springframework.data.annotation.Embedded;
3335
import org.springframework.data.annotation.Id;
3436
import org.springframework.data.geo.Point;
3537
import org.springframework.data.mongodb.core.DocumentTestUtils;
@@ -1282,9 +1284,34 @@ public void hashedIndexAndIndexViaComposedAnnotation() {
12821284
});
12831285
}
12841286

1285-
@Test
1286-
public void xxx() {
1287-
fail("TODO: index on embedded");
1287+
@Test // DATAMONGO-1902
1288+
public void resolvedIndexOnEmbeddedType() {
1289+
1290+
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(WithEmbedded.class,
1291+
EmbeddableType.class);
1292+
1293+
assertThat(indexDefinitions).hasSize(2);
1294+
assertThat(indexDefinitions.get(0)).satisfies(it -> {
1295+
assertThat(it.getIndexKeys()).containsEntry("stringValue", 1);
1296+
});
1297+
assertThat(indexDefinitions.get(1)).satisfies(it -> {
1298+
assertThat(it.getIndexKeys()).containsEntry("with-at-field-annotation", 1);
1299+
});
1300+
}
1301+
1302+
@Test // DATAMONGO-1902
1303+
public void resolvedIndexOnNestedEmbeddedType() {
1304+
1305+
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
1306+
WrapperAroundWithEmbedded.class, WithEmbedded.class, EmbeddableType.class);
1307+
1308+
assertThat(indexDefinitions).hasSize(2);
1309+
assertThat(indexDefinitions.get(0)).satisfies(it -> {
1310+
assertThat(it.getIndexKeys()).containsEntry("withEmbedded.stringValue", 1);
1311+
});
1312+
assertThat(indexDefinitions.get(1)).satisfies(it -> {
1313+
assertThat(it.getIndexKeys()).containsEntry("withEmbedded.with-at-field-annotation", 1);
1314+
});
12881315
}
12891316

12901317
@Document
@@ -1477,6 +1504,32 @@ static class OuterDocumentReferingToIndexedPropertyViaDifferentNonCyclingPaths {
14771504
AlternatePathToNoCycleButIndenticallNamedPropertiesDeeplyNestedDocument path2;
14781505
}
14791506

1507+
@Document
1508+
static class WrapperAroundWithEmbedded {
1509+
1510+
String id;
1511+
WithEmbedded withEmbedded;
1512+
}
1513+
1514+
@Document
1515+
static class WithEmbedded {
1516+
1517+
String id;
1518+
1519+
@Embedded.Nullable EmbeddableType embeddableType;
1520+
}
1521+
1522+
static class EmbeddableType {
1523+
1524+
@Indexed String stringValue;
1525+
1526+
List<String> listValue;
1527+
1528+
@Indexed //
1529+
@Field("with-at-field-annotation") //
1530+
String atFieldAnnotatedValue;
1531+
}
1532+
14801533
static class AlternatePathToNoCycleButIndenticallNamedPropertiesDeeplyNestedDocument {
14811534
NoCycleButIndenticallNamedPropertiesDeeplyNested propertyWithIndexedStructure;
14821535
}
@@ -1526,17 +1579,17 @@ class WithComposedHashedIndexAndIndex {
15261579
}
15271580
}
15281581

1529-
private static List<IndexDefinitionHolder> prepareMappingContextAndResolveIndexForType(Class<?> type) {
1582+
private static List<IndexDefinitionHolder> prepareMappingContextAndResolveIndexForType(Class<?>... types) {
15301583

1531-
MongoMappingContext mappingContext = prepareMappingContext(type);
1584+
MongoMappingContext mappingContext = prepareMappingContext(types);
15321585
MongoPersistentEntityIndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext);
1533-
return resolver.resolveIndexForEntity(mappingContext.getRequiredPersistentEntity(type));
1586+
return resolver.resolveIndexForEntity(mappingContext.getRequiredPersistentEntity(types[0]));
15341587
}
15351588

1536-
private static MongoMappingContext prepareMappingContext(Class<?> type) {
1589+
private static MongoMappingContext prepareMappingContext(Class<?>... types) {
15371590

15381591
MongoMappingContext mappingContext = new MongoMappingContext();
1539-
mappingContext.setInitialEntitySet(Collections.singleton(type));
1592+
mappingContext.setInitialEntitySet(new LinkedHashSet<>(Arrays.asList(types)));
15401593
mappingContext.initialize();
15411594

15421595
return mappingContext;

0 commit comments

Comments
 (0)