DATAMONGO-1183 - Polishing.
Tweak Javadoc and reference docs. Migrate tests to AssertJ. Remove not needed warning suppressions. Original pull request: #750.
This commit is contained in:
@@ -21,43 +21,37 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marker interface for a property that should be used as key for a
|
* Annotation for a property that should be used as key for a
|
||||||
* <a href="https://docs.mongodb.com/manual/core/index-hashed/">Hashed Index</a>. If used on a simple property the index
|
* <a href="https://docs.mongodb.com/manual/core/index-hashed/">Hashed Index</a>. If used on a simple property, the
|
||||||
* uses a hashing function to compute the hash of the value of the index field. Added to a property of complex type the
|
* index uses a hashing function to compute the hash of the value of the index field. Added to a property of complex
|
||||||
* embedded document is collapsed and the hash computed for the entire object.
|
* type the embedded document is collapsed and the hash computed for the entire object.
|
||||||
* <p />
|
* <p />
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <code>
|
|
||||||
*
|
*
|
||||||
|
* <pre class="code">
|
||||||
* @Document
|
* @Document
|
||||||
* public class DomainType {
|
* public class DomainType {
|
||||||
*
|
*
|
||||||
* @HashIndexed @Id String id;
|
* @HashIndexed @Id String id;
|
||||||
* }
|
* }
|
||||||
* </code>
|
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* {@link HashIndexed} can also be used as meta {@link java.lang.annotation.Annotation} to create composed annotations.
|
* {@link HashIndexed} can also be used as meta {@link java.lang.annotation.Annotation} to create composed annotations:
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <code>
|
|
||||||
*
|
*
|
||||||
|
* <pre class="code">
|
||||||
* @Indexed
|
* @Indexed
|
||||||
* @HashIndexed
|
* @HashIndexed
|
||||||
* @Retention(RetentionPolicy.RUNTIME)
|
* @Retention(RetentionPolicy.RUNTIME)
|
||||||
* public @interface IndexAndHash {
|
* public @interface IndexAndHash {
|
||||||
*
|
*
|
||||||
* @AliasFor(annotation = Indexed.class, attribute = "name")
|
* @AliasFor(annotation = Indexed.class, attribute = "name")
|
||||||
* String name() default "";
|
* String name() default "";
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @Document
|
* @Document
|
||||||
* public class DomainType {
|
* public class DomainType {
|
||||||
*
|
*
|
||||||
* @ComposedHashIndexed(name = "idx-name") String value;
|
* @ComposedHashIndexed(name = "idx-name") String value;
|
||||||
* }
|
* }
|
||||||
* </code>
|
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
@@ -67,5 +61,4 @@ import java.lang.annotation.Target;
|
|||||||
@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD })
|
@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD })
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface HashIndexed {
|
public @interface HashIndexed {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import org.springframework.util.ObjectUtils;
|
|||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public final class IndexField {
|
public final class IndexField {
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
|
|||||||
@@ -103,19 +103,20 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the {@link IndexDefinition}s for given {@literal root} entity by traversing {@link MongoPersistentProperty}
|
* Resolve the {@link IndexDefinition}s for a given {@literal root} entity by traversing
|
||||||
* scanning for index annotations {@link Indexed}, {@link CompoundIndex} and {@link GeospatialIndex}. The given
|
* {@link MongoPersistentProperty} scanning for index annotations {@link Indexed}, {@link CompoundIndex} and
|
||||||
* {@literal root} has therefore to be annotated with {@link Document}.
|
* {@link GeospatialIndex}. The given {@literal root} has therefore to be annotated with {@link Document}.
|
||||||
*
|
*
|
||||||
* @param root must not be null.
|
* @param root must not be null.
|
||||||
* @return List of {@link IndexDefinitionHolder}. Will never be {@code null}.
|
* @return List of {@link IndexDefinitionHolder}. Will never be {@code null}.
|
||||||
* @throws IllegalArgumentException in case of missing {@link Document} annotation marking root entities.
|
* @throws IllegalArgumentException in case of missing {@link Document} annotation marking root entities.
|
||||||
*/
|
*/
|
||||||
public List<IndexDefinitionHolder> resolveIndexForEntity(final MongoPersistentEntity<?> root) {
|
public List<IndexDefinitionHolder> resolveIndexForEntity(MongoPersistentEntity<?> root) {
|
||||||
|
|
||||||
Assert.notNull(root, "Index cannot be resolved for given 'null' entity.");
|
Assert.notNull(root, "MongoPersistentEntity must not be null!");
|
||||||
Document document = root.findAnnotation(Document.class);
|
Document document = root.findAnnotation(Document.class);
|
||||||
Assert.notNull(document, "Given entity is not collection root.");
|
Assert.notNull(document, () -> String
|
||||||
|
.format("Entity %s is not a collection root. Make sure to annotate it with @Document!", root.getName()));
|
||||||
|
|
||||||
List<IndexDefinitionHolder> indexInformation = new ArrayList<>();
|
List<IndexDefinitionHolder> indexInformation = new ArrayList<>();
|
||||||
String collection = root.getCollection();
|
String collection = root.getCollection();
|
||||||
@@ -201,7 +202,6 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private List<IndexDefinitionHolder> createIndexDefinitionHolderForProperty(String dotPath, String collection,
|
private List<IndexDefinitionHolder> createIndexDefinitionHolderForProperty(String dotPath, String collection,
|
||||||
MongoPersistentProperty persistentProperty) {
|
MongoPersistentProperty persistentProperty) {
|
||||||
|
|
||||||
@@ -328,7 +328,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create {@link IndexDefinition} wrapped in {@link IndexDefinitionHolder} for {@link CompoundIndexes} of given type.
|
* Create {@link IndexDefinition} wrapped in {@link IndexDefinitionHolder} for {@link CompoundIndexes} of a given
|
||||||
|
* type.
|
||||||
*
|
*
|
||||||
* @param dotPath The properties {@literal "dot"} path representation from its document root.
|
* @param dotPath The properties {@literal "dot"} path representation from its document root.
|
||||||
* @param fallbackCollection
|
* @param fallbackCollection
|
||||||
@@ -410,7 +411,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates {@link IndexDefinition} wrapped in {@link IndexDefinitionHolder} out of {@link Indexed} for given
|
* Creates {@link IndexDefinition} wrapped in {@link IndexDefinitionHolder} out of {@link Indexed} for a given
|
||||||
* {@link MongoPersistentProperty}.
|
* {@link MongoPersistentProperty}.
|
||||||
*
|
*
|
||||||
* @param dotPath The properties {@literal "dot"} path representation from its document root.
|
* @param dotPath The properties {@literal "dot"} path representation from its document root.
|
||||||
@@ -471,7 +472,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates {@link HashedIndex} wrapped in {@link IndexDefinitionHolder} out of {@link HashIndexed} for given
|
* Creates {@link HashedIndex} wrapped in {@link IndexDefinitionHolder} out of {@link HashIndexed} for a given
|
||||||
* {@link MongoPersistentProperty}.
|
* {@link MongoPersistentProperty}.
|
||||||
*
|
*
|
||||||
* @param dotPath The properties {@literal "dot"} path representation from its document root.
|
* @param dotPath The properties {@literal "dot"} path representation from its document root.
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ import com.mongodb.client.MongoDatabase;
|
|||||||
import com.mongodb.client.model.IndexOptions;
|
import com.mongodb.client.model.IndexOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Unit tests for {@link DefaultIndexOperations}.
|
||||||
|
*
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
*/
|
*/
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.mongodb.core.index;
|
package org.springframework.data.mongodb.core.index;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.*;
|
import static org.assertj.core.api.Assertions.*;
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.data.domain.Sort.Direction;
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,7 +27,6 @@ import org.springframework.data.domain.Sort.Direction;
|
|||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public class IndexFieldUnitTests {
|
public class IndexFieldUnitTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -35,9 +34,9 @@ public class IndexFieldUnitTests {
|
|||||||
|
|
||||||
IndexField field = IndexField.create("foo", Direction.ASC);
|
IndexField field = IndexField.create("foo", Direction.ASC);
|
||||||
|
|
||||||
assertThat(field.getKey(), is("foo"));
|
assertThat(field.getKey()).isEqualTo("foo");
|
||||||
assertThat(field.getDirection(), is(Direction.ASC));
|
assertThat(field.getDirection()).isEqualTo(Direction.ASC);
|
||||||
assertThat(field.isGeo(), is(false));
|
assertThat(field.isGeo()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -45,9 +44,9 @@ public class IndexFieldUnitTests {
|
|||||||
|
|
||||||
IndexField field = IndexField.geo("foo");
|
IndexField field = IndexField.geo("foo");
|
||||||
|
|
||||||
assertThat(field.getKey(), is("foo"));
|
assertThat(field.getKey()).isEqualTo("foo");
|
||||||
assertThat(field.getDirection(), is(nullValue()));
|
assertThat(field.getDirection()).isNull();
|
||||||
assertThat(field.isGeo(), is(true));
|
assertThat(field.isGeo()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -56,8 +55,8 @@ public class IndexFieldUnitTests {
|
|||||||
IndexField first = IndexField.create("foo", Direction.ASC);
|
IndexField first = IndexField.create("foo", Direction.ASC);
|
||||||
IndexField second = IndexField.create("foo", Direction.ASC);
|
IndexField second = IndexField.create("foo", Direction.ASC);
|
||||||
|
|
||||||
assertThat(first, is(second));
|
assertThat(first).isEqualTo(second);
|
||||||
assertThat(second, is(first));
|
assertThat(second).isEqualTo(first);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -66,13 +65,13 @@ public class IndexFieldUnitTests {
|
|||||||
IndexField first = IndexField.geo("bar");
|
IndexField first = IndexField.geo("bar");
|
||||||
IndexField second = IndexField.geo("bar");
|
IndexField second = IndexField.geo("bar");
|
||||||
|
|
||||||
assertThat(first, is(second));
|
assertThat(first).isEqualTo(second);
|
||||||
assertThat(second, is(first));
|
assertThat(second).isEqualTo(first);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // DATAMONGO-1183
|
@Test // DATAMONGO-1183
|
||||||
public void correctTypeForHashedFields() {
|
public void correctTypeForHashedFields() {
|
||||||
assertThat(IndexField.hashed("key").isHashed(), is(true));
|
assertThat(IndexField.hashed("key").isHashed()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // DATAMONGO-1183
|
@Test // DATAMONGO-1183
|
||||||
@@ -81,7 +80,7 @@ public class IndexFieldUnitTests {
|
|||||||
IndexField first = IndexField.hashed("bar");
|
IndexField first = IndexField.hashed("bar");
|
||||||
IndexField second = IndexField.hashed("bar");
|
IndexField second = IndexField.hashed("bar");
|
||||||
|
|
||||||
assertThat(first, is(second));
|
assertThat(first).isEqualTo(second);
|
||||||
assertThat(second, is(first));
|
assertThat(second).isEqualTo(first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1182,7 +1182,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
|||||||
|
|
||||||
assertThat(indexDefinitions).hasSize(1);
|
assertThat(indexDefinitions).hasSize(1);
|
||||||
assertThat(indexDefinitions.get(0)).satisfies(it -> {
|
assertThat(indexDefinitions.get(0)).satisfies(it -> {
|
||||||
assertThat(it.getIndexKeys()).isEqualTo(new org.bson.Document("_id", "hashed"));
|
assertThat(it.getIndexKeys()).hasSize(1).containsEntry("_id", "hashed");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1193,7 +1193,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
|||||||
|
|
||||||
assertThat(indexDefinitions).hasSize(1);
|
assertThat(indexDefinitions).hasSize(1);
|
||||||
assertThat(indexDefinitions.get(0)).satisfies(it -> {
|
assertThat(indexDefinitions.get(0)).satisfies(it -> {
|
||||||
assertThat(it.getIndexKeys()).isEqualTo(new org.bson.Document("value", "hashed"));
|
assertThat(it.getIndexKeys()).hasSize(1).containsEntry("value", "hashed");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1205,10 +1205,10 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
|||||||
|
|
||||||
assertThat(indexDefinitions).hasSize(2);
|
assertThat(indexDefinitions).hasSize(2);
|
||||||
assertThat(indexDefinitions.get(0)).satisfies(it -> {
|
assertThat(indexDefinitions.get(0)).satisfies(it -> {
|
||||||
assertThat(it.getIndexKeys()).isEqualTo(new org.bson.Document("value", 1));
|
assertThat(it.getIndexKeys()).containsEntry("value", 1);
|
||||||
});
|
});
|
||||||
assertThat(indexDefinitions.get(1)).satisfies(it -> {
|
assertThat(indexDefinitions.get(1)).satisfies(it -> {
|
||||||
assertThat(it.getIndexKeys()).isEqualTo(new org.bson.Document("value", "hashed"));
|
assertThat(it.getIndexKeys()).containsEntry("value", "hashed");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1220,11 +1220,11 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
|||||||
|
|
||||||
assertThat(indexDefinitions).hasSize(2);
|
assertThat(indexDefinitions).hasSize(2);
|
||||||
assertThat(indexDefinitions.get(0)).satisfies(it -> {
|
assertThat(indexDefinitions.get(0)).satisfies(it -> {
|
||||||
assertThat(it.getIndexKeys()).isEqualTo(new org.bson.Document("value", 1));
|
assertThat(it.getIndexKeys()).containsEntry("value", 1);
|
||||||
assertThat(it.getIndexOptions()).containsEntry("name", "idx-name");
|
assertThat(it.getIndexOptions()).containsEntry("name", "idx-name");
|
||||||
});
|
});
|
||||||
assertThat(indexDefinitions.get(1)).satisfies(it -> {
|
assertThat(indexDefinitions.get(1)).satisfies(it -> {
|
||||||
assertThat(it.getIndexKeys()).isEqualTo(new org.bson.Document("value", "hashed"));
|
assertThat(it.getIndexKeys()).containsEntry("value", "hashed");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
* Annotation-based Collation support through `@Document` and `@Query`.
|
* Annotation-based Collation support through `@Document` and `@Query`.
|
||||||
* <<mongodb.repositories.queries.aggregation, Aggregation framework>> support via repository query methods.
|
* <<mongodb.repositories.queries.aggregation, Aggregation framework>> support via repository query methods.
|
||||||
* Declarative reactive transactions using <<mongo.transactions.reactive-tx-manager, @Transactional>>.
|
* Declarative reactive transactions using <<mongo.transactions.reactive-tx-manager, @Transactional>>.
|
||||||
|
* Support for <<mapping-usage-indexes.hashed-index>>.
|
||||||
|
|
||||||
[[new-features.2-1-0]]
|
[[new-features.2-1-0]]
|
||||||
== What's New in Spring Data MongoDB 2.1
|
== What's New in Spring Data MongoDB 2.1
|
||||||
|
|||||||
@@ -606,8 +606,9 @@ public class Person {
|
|||||||
[[mapping-usage-indexes.hashed-index]]
|
[[mapping-usage-indexes.hashed-index]]
|
||||||
=== Hashed Indexes
|
=== Hashed Indexes
|
||||||
|
|
||||||
Hashed indexes allow hash based sharding within a sharded cluster. The hashed field value is used to shard collection results
|
Hashed indexes allow hash based sharding within a sharded cluster.
|
||||||
in a more random distribution. For details refer to the https://docs.mongodb.com/manual/core/index-hashed/[MongoDB Documentation].
|
Using hashed field values to shard collections results in a more random distribution.
|
||||||
|
For details, refer to the https://docs.mongodb.com/manual/core/index-hashed/[MongoDB Documentation].
|
||||||
|
|
||||||
Here's an example that creates a hashed index for `_id`:
|
Here's an example that creates a hashed index for `_id`:
|
||||||
|
|
||||||
@@ -625,7 +626,7 @@ public class DomainType {
|
|||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
Hashed indexes can be created next to other index definitions like shown below, in that case both indices will be created.
|
Hashed indexes can be created next to other index definitions like shown below, in that case both indices are created:
|
||||||
|
|
||||||
.Example Hashed Index Usage togehter with simple index
|
.Example Hashed Index Usage togehter with simple index
|
||||||
====
|
====
|
||||||
@@ -643,7 +644,7 @@ public class DomainType {
|
|||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
In case the above example is too verbose, a compound annotation allows to reduce the number of annotations present.
|
In case the example above is too verbose, a compound annotation allows to reduce the number of annotations that need to be declared on a property:
|
||||||
|
|
||||||
.Example Composed Hashed Index Usage
|
.Example Composed Hashed Index Usage
|
||||||
====
|
====
|
||||||
@@ -652,7 +653,7 @@ In case the above example is too verbose, a compound annotation allows to reduce
|
|||||||
@Document
|
@Document
|
||||||
public class DomainType {
|
public class DomainType {
|
||||||
|
|
||||||
@IndexAndHash(name = "idx...") <1>
|
@IndexAndHash(name = "idx...") <1>
|
||||||
String value;
|
String value;
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
@@ -672,7 +673,7 @@ public @interface IndexAndHash {
|
|||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
====
|
====
|
||||||
Although index creation via annotations comes in handy for many scenarios please cosider taking over more control by setting up indices manually via `IndexOperations`.
|
Although index creation via annotations comes in handy for many scenarios cosider taking over more control by setting up indices manually via `IndexOperations`.
|
||||||
|
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
@@ -684,7 +685,7 @@ mongoOperations.indexOpsFor(Jedi.class)
|
|||||||
[[mapping-usage-indexes.text-index]]
|
[[mapping-usage-indexes.text-index]]
|
||||||
=== Text Indexes
|
=== Text Indexes
|
||||||
|
|
||||||
NOTE: The text index feature is disabled by default for mongodb v.2.4.
|
NOTE: The text index feature is disabled by default for MongoDB v.2.4.
|
||||||
|
|
||||||
Creating a text index allows accumulating several fields into a searchable full-text index. It is only possible to have one text index per collection, so all fields marked with `@TextIndexed` are combined into this index. Properties can be weighted to influence the document score for ranking results. The default language for the text index is English. To change the default language, set the `language` attribute to whichever language you want (for example,`@Document(language="spanish")`). Using a property called `language` or `@Language` lets you define a language override on a per document base. The following example shows how to created a text index and set the language to Spanish:
|
Creating a text index allows accumulating several fields into a searchable full-text index. It is only possible to have one text index per collection, so all fields marked with `@TextIndexed` are combined into this index. Properties can be weighted to influence the document score for ranking results. The default language for the text index is English. To change the default language, set the `language` attribute to whichever language you want (for example,`@Document(language="spanish")`). Using a property called `language` or `@Language` lets you define a language override on a per document base. The following example shows how to created a text index and set the language to Spanish:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user