Skip to content

Commit 13a089e

Browse files
christophstroblodrotbohm
authored andcommitted
DATAMONGO-1297 - Allow @indexed annotation on DBRef.
We now also treat references as source of a potential index. This enforces index creation for Objects like: @document class WithDbRef { @indexed @DBREF ReferencedObject reference; } Combining @TextIndexed or @GeoSpatialIndexed with a DBRef will lead to a MappingException. Original pull request: #332.
1 parent 741a27e commit 13a089e

File tree

2 files changed

+102
-17
lines changed

2 files changed

+102
-17
lines changed

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

+55-17
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@
2727
import org.slf4j.LoggerFactory;
2828
import org.springframework.dao.InvalidDataAccessApiUsageException;
2929
import org.springframework.data.domain.Sort;
30+
import org.springframework.data.mapping.Association;
31+
import org.springframework.data.mapping.AssociationHandler;
3032
import org.springframework.data.mapping.PropertyHandler;
33+
import org.springframework.data.mapping.model.MappingException;
3134
import org.springframework.data.mongodb.core.index.Index.Duplicates;
3235
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.TextIndexIncludeOptions.IncludeStrategy;
3336
import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexDefinitionBuilder;
@@ -123,6 +126,8 @@ public void doWithPersistentProperty(MongoPersistentProperty persistentProperty)
123126
}
124127
});
125128

129+
indexInformation.addAll(resolveIndexesForDbrefs("", root.getCollection(), root));
130+
126131
return indexInformation;
127132
}
128133

@@ -168,6 +173,8 @@ public void doWithPersistentProperty(MongoPersistentProperty persistentProperty)
168173
}
169174
});
170175

176+
indexInformation.addAll(resolveIndexesForDbrefs(path, collection, entity));
177+
171178
return indexInformation;
172179
}
173180

@@ -193,18 +200,19 @@ private List<IndexDefinitionHolder> potentiallyCreateCompoundIndexDefinitions(St
193200
return createCompoundIndexDefinitions(dotPath, collection, entity);
194201
}
195202

196-
private Collection<? extends IndexDefinitionHolder> potentiallyCreateTextIndexDefinition(MongoPersistentEntity<?> root) {
203+
private Collection<? extends IndexDefinitionHolder> potentiallyCreateTextIndexDefinition(
204+
MongoPersistentEntity<?> root) {
197205

198-
TextIndexDefinitionBuilder indexDefinitionBuilder = new TextIndexDefinitionBuilder().named(root.getType()
199-
.getSimpleName() + "_TextIndex");
206+
TextIndexDefinitionBuilder indexDefinitionBuilder = new TextIndexDefinitionBuilder()
207+
.named(root.getType().getSimpleName() + "_TextIndex");
200208

201209
if (StringUtils.hasText(root.getLanguage())) {
202210
indexDefinitionBuilder.withDefaultLanguage(root.getLanguage());
203211
}
204212

205213
try {
206-
appendTextIndexInformation("", indexDefinitionBuilder, root,
207-
new TextIndexIncludeOptions(IncludeStrategy.DEFAULT), new CycleGuard());
214+
appendTextIndexInformation("", indexDefinitionBuilder, root, new TextIndexIncludeOptions(IncludeStrategy.DEFAULT),
215+
new CycleGuard());
208216
} catch (CyclicPropertyReferenceException e) {
209217
LOGGER.info(e.getMessage());
210218
}
@@ -220,9 +228,8 @@ private Collection<? extends IndexDefinitionHolder> potentiallyCreateTextIndexDe
220228

221229
}
222230

223-
private void appendTextIndexInformation(final String dotPath,
224-
final TextIndexDefinitionBuilder indexDefinitionBuilder, final MongoPersistentEntity<?> entity,
225-
final TextIndexIncludeOptions includeOptions, final CycleGuard guard) {
231+
private void appendTextIndexInformation(final String dotPath, final TextIndexDefinitionBuilder indexDefinitionBuilder,
232+
final MongoPersistentEntity<?> entity, final TextIndexIncludeOptions includeOptions, final CycleGuard guard) {
226233

227234
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
228235

@@ -249,8 +256,8 @@ public void doWithPersistentProperty(MongoPersistentProperty persistentProperty)
249256

250257
TextIndexIncludeOptions optionsForNestedType = includeOptions;
251258
if (!IncludeStrategy.FORCE.equals(includeOptions.getStrategy()) && indexed != null) {
252-
optionsForNestedType = new TextIndexIncludeOptions(IncludeStrategy.FORCE, new TextIndexedFieldSpec(
253-
propertyDotPath, weight));
259+
optionsForNestedType = new TextIndexIncludeOptions(IncludeStrategy.FORCE,
260+
new TextIndexedFieldSpec(propertyDotPath, weight));
254261
}
255262

256263
try {
@@ -259,9 +266,8 @@ public void doWithPersistentProperty(MongoPersistentProperty persistentProperty)
259266
} catch (CyclicPropertyReferenceException e) {
260267
LOGGER.info(e.getMessage(), e);
261268
} catch (InvalidDataAccessApiUsageException e) {
262-
LOGGER.info(
263-
String.format("Potentially invalid index structure discovered. Breaking operation for %s.",
264-
entity.getName()), e);
269+
LOGGER.info(String.format("Potentially invalid index structure discovered. Breaking operation for %s.",
270+
entity.getName()), e);
265271
}
266272
} else if (includeOptions.isForce() || indexed != null) {
267273
indexDefinitionBuilder.onField(propertyDotPath, weight);
@@ -306,8 +312,8 @@ protected List<IndexDefinitionHolder> createCompoundIndexDefinitions(String dotP
306312
protected IndexDefinitionHolder createCompoundIndexDefinition(String dotPath, String fallbackCollection,
307313
CompoundIndex index, MongoPersistentEntity<?> entity) {
308314

309-
CompoundIndexDefinition indexDefinition = new CompoundIndexDefinition(resolveCompoundIndexKeyFromStringDefinition(
310-
dotPath, index.def()));
315+
CompoundIndexDefinition indexDefinition = new CompoundIndexDefinition(
316+
resolveCompoundIndexKeyFromStringDefinition(dotPath, index.def()));
311317

312318
if (!index.useGeneratedName()) {
313319
indexDefinition.named(pathAwareIndexName(index.name(), dotPath, null));
@@ -431,13 +437,45 @@ private String pathAwareIndexName(String indexName, String dotPath, MongoPersist
431437

432438
if (StringUtils.hasText(dotPath)) {
433439

434-
nameToUse = StringUtils.hasText(nameToUse) ? (property != null ? dotPath.replace("." + property.getFieldName(),
435-
"") : dotPath) + "." + nameToUse : dotPath;
440+
nameToUse = StringUtils.hasText(nameToUse)
441+
? (property != null ? dotPath.replace("." + property.getFieldName(), "") : dotPath) + "." + nameToUse
442+
: dotPath;
436443
}
437444
return nameToUse;
438445

439446
}
440447

448+
private List<IndexDefinitionHolder> resolveIndexesForDbrefs(final String path, final String collection,
449+
MongoPersistentEntity<?> entity) {
450+
451+
final List<IndexDefinitionHolder> indexes = new ArrayList<IndexDefinitionHolder>(0);
452+
entity.doWithAssociations(new AssociationHandler<MongoPersistentProperty>() {
453+
454+
@Override
455+
public void doWithAssociation(Association<MongoPersistentProperty> association) {
456+
457+
MongoPersistentProperty property = association.getInverse();
458+
459+
String propertyDotPath = (StringUtils.hasText(path) ? path + "." : "") + property.getFieldName();
460+
461+
if (property.isAnnotationPresent(GeoSpatialIndexed.class) || property.isAnnotationPresent(TextIndexed.class)) {
462+
throw new MappingException(
463+
String.format("Cannot create geospatial-/text- index on DBRef in collection '%s' for path '%s'.",
464+
collection, propertyDotPath));
465+
}
466+
467+
IndexDefinitionHolder indexDefinitionHolder = createIndexDefinitionHolderForProperty(propertyDotPath,
468+
collection, property);
469+
470+
if (indexDefinitionHolder != null) {
471+
indexes.add(indexDefinitionHolder);
472+
}
473+
}
474+
});
475+
476+
return indexes;
477+
}
478+
441479
/**
442480
* {@link CycleGuard} holds information about properties and the paths for accessing those. This information is used
443481
* to detect potential cycles within the references.

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

+47
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.junit.runner.RunWith;
2727
import org.junit.runners.Suite;
2828
import org.junit.runners.Suite.SuiteClasses;
29+
import org.springframework.data.annotation.Id;
2930
import org.springframework.data.geo.Point;
3031
import org.springframework.data.mongodb.core.DBObjectTestUtils;
3132
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.IndexDefinitionHolder;
@@ -148,6 +149,34 @@ public void resolvesIndexCollectionNameCorrectlyWhenDefinedInAnnotation() {
148149
assertThat(indexDefinitions.get(0).getCollection(), equalTo("CollectionOverride"));
149150
}
150151

152+
/**
153+
* @see DATAMONGO-1297
154+
*/
155+
@Test
156+
public void resolvesIndexOnDbrefWhenDefined() {
157+
158+
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(WithDbRef.class);
159+
160+
assertThat(indexDefinitions, hasSize(1));
161+
assertThat(indexDefinitions.get(0).getCollection(), equalTo("withDbRef"));
162+
assertThat(indexDefinitions.get(0).getIndexKeys(), equalTo(new BasicDBObjectBuilder().add("indexedDbRef", 1)
163+
.get()));
164+
}
165+
166+
/**
167+
* @see DATAMONGO-1297
168+
*/
169+
@Test
170+
public void resolvesIndexOnDbrefWhenDefinedOnNestedElement() {
171+
172+
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(WrapperOfWithDbRef.class);
173+
174+
assertThat(indexDefinitions, hasSize(1));
175+
assertThat(indexDefinitions.get(0).getCollection(), equalTo("wrapperOfWithDbRef"));
176+
assertThat(indexDefinitions.get(0).getIndexKeys(),
177+
equalTo(new BasicDBObjectBuilder().add("nested.indexedDbRef", 1).get()));
178+
}
179+
151180
@Document(collection = "Zero")
152181
static class IndexOnLevelZero {
153182
@Indexed String indexedProperty;
@@ -182,6 +211,24 @@ static class IndexOnLevelZeroWithExplicityNamedField {
182211
@Indexed @Field("customFieldName") String namedProperty;
183212
}
184213

214+
@Document
215+
static class WrapperOfWithDbRef {
216+
WithDbRef nested;
217+
}
218+
219+
@Document
220+
static class WithDbRef {
221+
222+
@Indexed//
223+
@DBRef//
224+
NoIndex indexedDbRef;
225+
}
226+
227+
@Document(collection = "no-index")
228+
static class NoIndex {
229+
@Id String id;
230+
}
231+
185232
}
186233

187234
/**

0 commit comments

Comments
 (0)