Browse Source

next on list is transactions

labs/antora
Christoph Strobl 2 years ago
parent
commit
d7094416a4
No known key found for this signature in database
GPG Key ID: 8CC1AB53391458C8
  1. 7
      src/main/antora/modules/ROOT/nav.adoc
  2. 16
      src/main/antora/modules/ROOT/pages/mongodb/mapping/custom-conversions.adoc
  3. 4
      src/main/antora/modules/ROOT/pages/mongodb/mapping/entity-callbacks.adoc
  4. 6
      src/main/antora/modules/ROOT/pages/mongodb/mapping/lifecycle-events.adoc
  5. 340
      src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping-index-management.adoc
  6. 390
      src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping.adoc
  7. 15
      src/main/antora/modules/ROOT/pages/mongodb/mapping/property-converters.adoc

7
src/main/antora/modules/ROOT/nav.adoc

@ -18,12 +18,13 @@ @@ -18,12 +18,13 @@
**** xref:mongodb/template-collection-schema.adoc[]
*** xref:mongodb/template-gridfs.adoc[]
** xref:mongodb/mapping/mapping.adoc[]
*** xref:mongodb/mapping/custom-conversions.adoc[]
*** xref:mongodb/mapping/custom-conversions.adoc[Type based Converter]
*** xref:mongodb/mapping/property-converters.adoc[]
*** xref:mongodb/mapping/unwrapping-entities.adoc[]
*** xref:mongodb/mapping/document-references.adoc[]
*** xref:mongodb/mapping/entity-callbacks.adoc[]
*** xref:mongodb/mapping/document-references.adoc[Object References]
*** xref:mongodb/mapping/entity-callbacks.adoc[Entity Callbacks]
*** xref:mongodb/mapping/lifecycle-events.adoc[]
*** xref:mongodb/mapping/mapping-index-management.adoc[]
** xref:mongodb/client-session-transactions.adoc[]
** xref:mongodb/change-streams.adoc[]
** xref:mongodb/tailable-cursors.adoc[]

16
src/main/antora/modules/ROOT/pages/mongodb/mapping/custom-conversions.adoc

@ -1,9 +1,10 @@ @@ -1,9 +1,10 @@
include::{commons}@data-commons::page$custom-conversions.adoc[]
[[mongo.custom-converters]]
= Custom Conversions - Overriding Default Mapping
== Type based Converter
The most trivial way of influencing the mapping result is by specifying the desired native MongoDB target type via the
`@Field` annotation. This allows to work with non MongoDB types like `BigDecimal` in the domain model while persisting
values in native `org.bson.types.Decimal128` format.
The most trivial way of influencing the mapping result is by specifying the desired native MongoDB target type via the `@Field` annotation.
This allows to work with non MongoDB types like `BigDecimal` in the domain model while persisting values in native `org.bson.types.Decimal128` format.
.Explicit target type mapping
====
@ -20,6 +21,7 @@ public class Payment { @@ -20,6 +21,7 @@ public class Payment {
}
----
[source,java]
----
{
@ -43,7 +45,7 @@ The `MappingMongoConverter` checks to see if any Spring converters can handle a @@ -43,7 +45,7 @@ The `MappingMongoConverter` checks to see if any Spring converters can handle a
NOTE: For more information on the Spring type conversion service, see the reference docs link:{springDocsUrl}/core.html#validation[here].
[[mongo.custom-converters.writer]]
== Saving by Using a Registered Spring Converter
=== Writing Converter
The following example shows an implementation of the `Converter` that converts from a `Person` object to a `org.bson.Document`:
@ -66,7 +68,7 @@ public class PersonWriteConverter implements Converter<Person, Document> { @@ -66,7 +68,7 @@ public class PersonWriteConverter implements Converter<Person, Document> {
----
[[mongo.custom-converters.reader]]
== Reading by Using a Spring Converter
=== Reading Converter
The following example shows an implementation of a `Converter` that converts from a `Document` to a `Person` object:
@ -83,7 +85,7 @@ public class PersonReadConverter implements Converter<Document, Person> { @@ -83,7 +85,7 @@ public class PersonReadConverter implements Converter<Document, Person> {
----
[[mongo.custom-converters.xml]]
== Registering Spring Converters with the `MongoConverter`
=== Registering Converters
[source,java]
----

4
src/main/antora/modules/ROOT/pages/mongodb/mapping/entity-callbacks.adoc

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
include::{commons}@data-commons::page$entity-callbacks.adoc[]
[[mongo.entity-callbacks]]
= Store specific EntityCallbacks
== Store specific EntityCallbacks
Spring Data MongoDB uses the `EntityCallback` API for its auditing support and reacts on the following callbacks.

6
src/main/antora/modules/ROOT/pages/mongodb/mapping/lifecycle-events.adoc

@ -39,13 +39,15 @@ public class BeforeSaveListener extends AbstractMongoEventListener<Person> { @@ -39,13 +39,15 @@ public class BeforeSaveListener extends AbstractMongoEventListener<Person> {
Declaring these beans in your Spring ApplicationContext causes them to be invoked whenever the event is dispatched.
The following callback methods are present in `AbstractMappingEventListener`:
.Callbacks on `AbstractMappingEventListener`:
[%collapsible]
====
* `onBeforeConvert`: Called in `MongoTemplate` `insert`, `insertList`, and `save` operations before the object is converted to a `Document` by a `MongoConverter`.
* `onBeforeSave`: Called in `MongoTemplate` `insert`, `insertList`, and `save` operations *before* inserting or saving the `Document` in the database.
* `onAfterSave`: Called in `MongoTemplate` `insert`, `insertList`, and `save` operations *after* inserting or saving the `Document` in the database.
* `onAfterLoad`: Called in `MongoTemplate` `find`, `findAndRemove`, `findOne`, and `getCollection` methods after the `Document` has been retrieved from the database.
* `onAfterConvert`: Called in `MongoTemplate` `find`, `findAndRemove`, `findOne`, and `getCollection` methods after the `Document` has been retrieved from the database was converted to a POJO.
====
NOTE: Lifecycle events are only emitted for root level types. Complex types used as properties within a document root are not subject to event publication unless they are document references annotated with `@DBRef`.

340
src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping-index-management.adoc

@ -0,0 +1,340 @@ @@ -0,0 +1,340 @@
[[mapping.index-creation]]
= Index Creation
Spring Data MongoDB can automatically create indexes for entity types annotated with `@Document`.
Index creation must be explicitly enabled since version 3.0 to prevent undesired effects with collection lifecyle and performance impact.
Indexes are automatically created for the initial entity set on application startup and when accessing an entity type for the first time while the application runs.
We generally recommend explicit index creation for application-based control of indexes as Spring Data cannot automatically create indexes for collections that were recreated while the application was running.
`IndexResolver` provides an abstraction for programmatic index definition creation if you want to make use of `@Indexed` annotations such as `@GeoSpatialIndexed`, `@TextIndexed`, `@CompoundIndex` and `@WildcardIndexed`.
You can use index definitions with `IndexOperations` to create indexes.
A good point in time for index creation is on application startup, specifically after the application context was refreshed, triggered by observing `ContextRefreshedEvent`.
This event guarantees that the context is fully initialized.
Note that at this time other components, especially bean factories might have access to the MongoDB database.
[WARNING]
====
``Map``-like properties are skipped by the `IndexResolver` unless annotated with `@WildcardIndexed` because the _map key_ must be part of the index definition. Since the purpose of maps is the usage of dynamic keys and values, the keys cannot be resolved from static mapping metadata.
====
.Programmatic Index Creation for a single Domain Type
====
[source,java]
----
class MyListener {
@EventListener(ContextRefreshedEvent.class)
public void initIndicesAfterStartup() {
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext = mongoTemplate
.getConverter().getMappingContext();
IndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext);
IndexOperations indexOps = mongoTemplate.indexOps(DomainType.class);
resolver.resolveIndexFor(DomainType.class).forEach(indexOps::ensureIndex);
}
}
----
====
.Programmatic Index Creation for all Initial Entities
====
[source,java]
----
class MyListener{
@EventListener(ContextRefreshedEvent.class)
public void initIndicesAfterStartup() {
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext = mongoTemplate
.getConverter().getMappingContext();
// consider only entities that are annotated with @Document
mappingContext.getPersistentEntities()
.stream()
.filter(it -> it.isAnnotationPresent(Document.class))
.forEach(it -> {
IndexOperations indexOps = mongoTemplate.indexOps(it.getType());
resolver.resolveIndexFor(it.getType()).forEach(indexOps::ensureIndex);
});
}
}
----
====
Alternatively, if you want to ensure index and collection presence before any component is able to access your database from your application, declare a `@Bean` method for `MongoTemplate` and include the code from above before returning the `MongoTemplate` object.
[NOTE]
====
To turn automatic index creation _ON_ please override `autoIndexCreation()` in your configuration.
[source,java]
----
@Configuration
public class Config extends AbstractMongoClientConfiguration {
@Override
public boolean autoIndexCreation() {
return true;
}
// ...
}
----
====
IMPORTANT: Automatic index creation is turned _OFF_ by default as of version 3.0.
[[mapping-usage-indexes.compound-index]]
== Compound Indexes
Compound indexes are also supported. They are defined at the class level, rather than on individual properties.
NOTE: Compound indexes are very important to improve the performance of queries that involve criteria on multiple fields
Here's an example that creates a compound index of `lastName` in ascending order and `age` in descending order:
.Example Compound Index Usage
====
[source,java]
----
package com.mycompany.domain;
@Document
@CompoundIndex(name = "age_idx", def = "{'lastName': 1, 'age': -1}")
public class Person {
@Id
private ObjectId id;
private Integer age;
private String firstName;
private String lastName;
}
----
====
[TIP]
====
`@CompoundIndex` is repeatable using `@CompoundIndexes` as its container.
[source,java]
----
@Document
@CompoundIndex(name = "cmp-idx-one", def = "{'firstname': 1, 'lastname': -1}")
@CompoundIndex(name = "cmp-idx-two", def = "{'address.city': -1, 'address.street': 1}")
public class Person {
String firstname;
String lastname;
Address address;
// ...
}
----
====
[[mapping-usage-indexes.hashed-index]]
== Hashed Indexes
Hashed indexes allow hash based sharding within a sharded cluster.
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`:
.Example Hashed Index Usage
====
[source,java]
----
@Document
public class DomainType {
@HashIndexed @Id String id;
// ...
}
----
====
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
====
[source,java]
----
@Document
public class DomainType {
@Indexed
@HashIndexed
String value;
// ...
}
----
====
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
====
[source,java]
----
@Document
public class DomainType {
@IndexAndHash(name = "idx...") <1>
String value;
// ...
}
@Indexed
@HashIndexed
@Retention(RetentionPolicy.RUNTIME)
public @interface IndexAndHash {
@AliasFor(annotation = Indexed.class, attribute = "name") <1>
String name() default "";
}
----
<1> Potentially register an alias for certain attributes of the meta annotation.
====
[NOTE]
====
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]
----
mongoOperations.indexOpsFor(Jedi.class)
.ensureIndex(HashedIndex.hashed("useTheForce"));
----
====
[[mapping-usage-indexes.wildcard-index]]
== Wildcard Indexes
A `WildcardIndex` is an index that can be used to include all fields or specific ones based a given (wildcard) pattern.
For details, refer to the https://docs.mongodb.com/manual/core/index-wildcard/[MongoDB Documentation].
The index can be set up programmatically using `WildcardIndex` via `IndexOperations`.
.Programmatic WildcardIndex setup
====
[source,java]
----
mongoOperations
.indexOps(User.class)
.ensureIndex(new WildcardIndex("userMetadata"));
----
[source,javascript]
----
db.user.createIndex({ "userMetadata.$**" : 1 }, {})
----
====
The `@WildcardIndex` annotation allows a declarative index setup that can used either with a document type or property.
If placed on a type that is a root level domain entity (one annotated with `@Document`) , the index resolver will create a
wildcard index for it.
.Wildcard index on domain type
====
[source,java]
----
@Document
@WildcardIndexed
public class Product {
// …
}
----
[source,javascript]
----
db.product.createIndex({ "$**" : 1 },{})
----
====
The `wildcardProjection` can be used to specify keys to in-/exclude in the index.
.Wildcard index with `wildcardProjection`
====
[source,java]
----
@Document
@WildcardIndexed(wildcardProjection = "{ 'userMetadata.age' : 0 }")
public class User {
private @Id String id;
private UserMetadata userMetadata;
}
----
[source,javascript]
----
db.user.createIndex(
{ "$**" : 1 },
{ "wildcardProjection" :
{ "userMetadata.age" : 0 }
}
)
----
====
Wildcard indexes can also be expressed by adding the annotation directly to the field.
Please note that `wildcardProjection` is not allowed on nested paths such as properties.
Projections on types annotated with `@WildcardIndexed` are omitted during index creation.
.Wildcard index on property
====
[source,java]
----
@Document
public class User {
private @Id String id;
@WildcardIndexed
private UserMetadata userMetadata;
}
----
[source,javascript]
----
db.user.createIndex({ "userMetadata.$**" : 1 }, {})
----
====
[[mapping-usage-indexes.text-index]]
== Text Indexes
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:
.Example Text Index Usage
====
[source,java]
----
@Document(language = "spanish")
class SomeEntity {
@TextIndexed String foo;
@Language String lang;
Nested nested;
}
class Nested {
@TextIndexed(weight=5) String bar;
String roo;
}
----
====

390
src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping.adoc

@ -1,7 +1,8 @@ @@ -1,7 +1,8 @@
[[mapping-chapter]]
= Object Mapping
Rich mapping support is provided by the `MappingMongoConverter`. `MappingMongoConverter` has a rich metadata model that provides a full feature set to map domain objects to MongoDB documents.
Rich mapping support is provided by the `MappingMongoConverter`.
The converter holds a metadata model that provides a full feature set to map domain objects to MongoDB documents.
The mapping metadata model is populated by using annotations on your domain objects.
However, the infrastructure is not limited to using annotations as the only source of metadata information.
The `MappingMongoConverter` also lets you map objects to documents without providing any additional metadata, by following a set of conventions.
@ -65,11 +66,14 @@ When querying and updating `MongoTemplate` will use the converter to handle conv @@ -65,11 +66,14 @@ When querying and updating `MongoTemplate` will use the converter to handle conv
[[mapping-conversion]]
== Data Mapping and Type Conversion
This section explains how types are mapped to and from a MongoDB representation. Spring Data MongoDB supports all types that can be represented as BSON, MongoDB's internal document format.
In addition to these types, Spring Data MongoDB provides a set of built-in converters to map additional types. You can provide your own converters to adjust type conversion. See xref:mongodb/mapping/custom-conversions.adoc[Custom Conversions - Overriding Default Mapping] for further details.
The following provides samples of each available type conversion:
Spring Data MongoDB supports all types that can be represented as BSON, MongoDB's internal document format.
In addition to these types, Spring Data MongoDB provides a set of built-in converters to map additional types.
You can provide your own converters to adjust type conversion.
See xref:mongodb/mapping/custom-conversions.adoc[Custom Conversions - Overriding Default Mapping] for further details.
.Built in Type conversions:
[%collapsible]
====
[cols="3,1,6", options="header"]
.Type
|===
@ -256,7 +260,7 @@ calling `get()` before the actual conversion @@ -256,7 +260,7 @@ calling `get()` before the actual conversion
[ [ -73.97880 , 40.77247 ], [ -73.97036 , 40.76811 ] ]
] }}`
|===
====
[[mapping-configuration]]
== Mapping Configuration
@ -265,9 +269,12 @@ Unless explicitly configured, an instance of `MappingMongoConverter` is created @@ -265,9 +269,12 @@ Unless explicitly configured, an instance of `MappingMongoConverter` is created
You can configure the `MappingMongoConverter` as well as `com.mongodb.client.MongoClient` and MongoTemplate by using either Java-based or XML-based metadata. The following example shows the configuration:
====
.Java
[source,java,role="primary"]
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Configuration
public class MongoConfig extends AbstractMongoClientConfiguration {
@ -296,11 +303,13 @@ public class MongoConfig extends AbstractMongoClientConfiguration { @@ -296,11 +303,13 @@ public class MongoConfig extends AbstractMongoClientConfiguration {
return new LoggingEventListener<MongoMappingEvent>();
}
}
----
<1> The mapping base package defines the root path used to scan for entities used to pre initialize the `MappingContext`. By default the configuration classes package is used.
<2> Configure additional custom converters for specific domain types that replace the default mapping procedure for those types with your custom implementation.
.XML
[source,xml,role="secondary"]
XML::
+
[source,xml,indent=0,subs="verbatim,quotes",role="secondary"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
@ -337,11 +346,10 @@ public class MongoConfig extends AbstractMongoClientConfiguration { @@ -337,11 +346,10 @@ public class MongoConfig extends AbstractMongoClientConfiguration {
</beans>
----
<1> The mapping base package defines the root path used to scan for entities used to pre initialize the `MappingContext`. By default the configuration classes package is used.
<2> Configure additional custom converters for specific domain types that replace the default mapping procedure for those types with your custom implementation.
====
======
`AbstractMongoClientConfiguration` requires you to implement methods that define a `com.mongodb.client.MongoClient` as well as provide a database name. `AbstractMongoClientConfiguration` also has a method named `getMappingBasePackage(…)` that you can override to tell the converter where to scan for classes annotated with the `@Document` annotation.
`AbstractMongoClientConfiguration` requires you to implement methods that define a `com.mongodb.client.MongoClient` as well as provide a database name.
`AbstractMongoClientConfiguration` also has a method named `getMappingBasePackage(…)` that you can override to tell the converter where to scan for classes annotated with the `@Document` annotation.
You can add additional converters to the converter by overriding the `customConversionsConfiguration` method.
MongoDB's native JSR-310 support can be enabled through `MongoConverterConfigurationAdapter.useNativeDriverJavaTimeCodecs()`.
@ -402,95 +410,6 @@ Automatic index creation is only done for types annotated with `@Document`. @@ -402,95 +410,6 @@ Automatic index creation is only done for types annotated with `@Document`.
WARNING: Auto index creation is **disabled** by default and needs to be enabled through the configuration (see xref:mongodb/mapping/mapping.adoc#mapping.index-creation[Index Creation]).
[[mapping.index-creation]]
=== Index Creation
Spring Data MongoDB can automatically create indexes for entity types annotated with `@Document`.
Index creation must be explicitly enabled since version 3.0 to prevent undesired effects with collection lifecyle and performance impact.
Indexes are automatically created for the initial entity set on application startup and when accessing an entity type for the first time while the application runs.
We generally recommend explicit index creation for application-based control of indexes as Spring Data cannot automatically create indexes for collections that were recreated while the application was running.
`IndexResolver` provides an abstraction for programmatic index definition creation if you want to make use of `@Indexed` annotations such as `@GeoSpatialIndexed`, `@TextIndexed`, `@CompoundIndex` and `@WildcardIndexed`.
You can use index definitions with `IndexOperations` to create indexes.
A good point in time for index creation is on application startup, specifically after the application context was refreshed, triggered by observing `ContextRefreshedEvent`.
This event guarantees that the context is fully initialized.
Note that at this time other components, especially bean factories might have access to the MongoDB database.
[WARNING]
====
``Map``-like properties are skipped by the `IndexResolver` unless annotated with `@WildcardIndexed` because the _map key_ must be part of the index definition. Since the purpose of maps is the usage of dynamic keys and values, the keys cannot be resolved from static mapping metadata.
====
.Programmatic Index Creation for a single Domain Type
====
[source,java]
----
class MyListener {
@EventListener(ContextRefreshedEvent.class)
public void initIndicesAfterStartup() {
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext = mongoTemplate
.getConverter().getMappingContext();
IndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext);
IndexOperations indexOps = mongoTemplate.indexOps(DomainType.class);
resolver.resolveIndexFor(DomainType.class).forEach(indexOps::ensureIndex);
}
}
----
====
.Programmatic Index Creation for all Initial Entities
====
[source,java]
----
class MyListener{
@EventListener(ContextRefreshedEvent.class)
public void initIndicesAfterStartup() {
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext = mongoTemplate
.getConverter().getMappingContext();
// consider only entities that are annotated with @Document
mappingContext.getPersistentEntities()
.stream()
.filter(it -> it.isAnnotationPresent(Document.class))
.forEach(it -> {
IndexOperations indexOps = mongoTemplate.indexOps(it.getType());
resolver.resolveIndexFor(it.getType()).forEach(indexOps::ensureIndex);
});
}
}
----
====
Alternatively, if you want to ensure index and collection presence before any component is able to access your database from your application, declare a `@Bean` method for `MongoTemplate` and include the code from above before returning the `MongoTemplate` object.
[NOTE]
====
To turn automatic index creation _ON_ please override `autoIndexCreation()` in your configuration.
[source,java]
----
@Configuration
public class Config extends AbstractMongoClientConfiguration {
@Override
public boolean autoIndexCreation() {
return true;
}
// ...
}
----
====
IMPORTANT: Automatic index creation is turned _OFF_ by default as of version 3.0.
[[mapping-usage-annotations]]
=== Mapping Annotation Overview
@ -515,8 +434,9 @@ The MappingMongoConverter can use metadata to drive the mapping of objects to do @@ -515,8 +434,9 @@ The MappingMongoConverter can use metadata to drive the mapping of objects to do
The mapping metadata infrastructure is defined in a separate spring-data-commons project that is technology agnostic. Specific subclasses are using in the MongoDB support to support annotation based metadata. Other strategies are also possible to put in place if there is demand.
Here is an example of a more complex mapping.
.Here is an example of a more complex mapping
[%collapsible]
====
[source,java]
----
@Document
@ -571,6 +491,7 @@ public class Person<T extends Address> { @@ -571,6 +491,7 @@ public class Person<T extends Address> {
// other getters/setters omitted
}
----
====
[TIP]
====
@ -645,264 +566,9 @@ NOTE: The SpEL expression in the `@Value` annotation of the `quantity` parameter @@ -645,264 +566,9 @@ NOTE: The SpEL expression in the `@Value` annotation of the `quantity` parameter
Additional examples for using the `@PersistenceConstructor` annotation can be found in the https://github.com/spring-projects/spring-data-mongodb/blob/master/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java[MappingMongoConverterUnitTests] test suite.
[[mapping-usage-indexes.compound-index]]
=== Compound Indexes
Compound indexes are also supported. They are defined at the class level, rather than on individual properties.
NOTE: Compound indexes are very important to improve the performance of queries that involve criteria on multiple fields
Here's an example that creates a compound index of `lastName` in ascending order and `age` in descending order:
.Example Compound Index Usage
====
[source,java]
----
package com.mycompany.domain;
@Document
@CompoundIndex(name = "age_idx", def = "{'lastName': 1, 'age': -1}")
public class Person {
@Id
private ObjectId id;
private Integer age;
private String firstName;
private String lastName;
}
----
====
[TIP]
====
`@CompoundIndex` is repeatable using `@CompoundIndexes` as its container.
[source,java]
----
@Document
@CompoundIndex(name = "cmp-idx-one", def = "{'firstname': 1, 'lastname': -1}")
@CompoundIndex(name = "cmp-idx-two", def = "{'address.city': -1, 'address.street': 1}")
public class Person {
String firstname;
String lastname;
Address address;
// ...
}
----
====
[[mapping-usage-indexes.hashed-index]]
=== Hashed Indexes
Hashed indexes allow hash based sharding within a sharded cluster.
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`:
.Example Hashed Index Usage
====
[source,java]
----
@Document
public class DomainType {
@HashIndexed @Id String id;
// ...
}
----
====
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
====
[source,java]
----
@Document
public class DomainType {
@Indexed
@HashIndexed
String value;
// ...
}
----
====
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
====
[source,java]
----
@Document
public class DomainType {
@IndexAndHash(name = "idx...") <1>
String value;
// ...
}
@Indexed
@HashIndexed
@Retention(RetentionPolicy.RUNTIME)
public @interface IndexAndHash {
@AliasFor(annotation = Indexed.class, attribute = "name") <1>
String name() default "";
}
----
<1> Potentially register an alias for certain attributes of the meta annotation.
====
[NOTE]
====
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]
----
mongoOperations.indexOpsFor(Jedi.class)
.ensureIndex(HashedIndex.hashed("useTheForce"));
----
====
[[mapping-usage-indexes.wildcard-index]]
=== Wildcard Indexes
A `WildcardIndex` is an index that can be used to include all fields or specific ones based a given (wildcard) pattern.
For details, refer to the https://docs.mongodb.com/manual/core/index-wildcard/[MongoDB Documentation].
The index can be set up programmatically using `WildcardIndex` via `IndexOperations`.
.Programmatic WildcardIndex setup
====
[source,java]
----
mongoOperations
.indexOps(User.class)
.ensureIndex(new WildcardIndex("userMetadata"));
----
[source,javascript]
----
db.user.createIndex({ "userMetadata.$**" : 1 }, {})
----
====
The `@WildcardIndex` annotation allows a declarative index setup that can used either with a document type or property.
If placed on a type that is a root level domain entity (one annotated with `@Document`) , the index resolver will create a
wildcard index for it.
.Wildcard index on domain type
====
[source,java]
----
@Document
@WildcardIndexed
public class Product {
// …
}
----
[source,javascript]
----
db.product.createIndex({ "$**" : 1 },{})
----
====
The `wildcardProjection` can be used to specify keys to in-/exclude in the index.
.Wildcard index with `wildcardProjection`
====
[source,java]
----
@Document
@WildcardIndexed(wildcardProjection = "{ 'userMetadata.age' : 0 }")
public class User {
private @Id String id;
private UserMetadata userMetadata;
}
----
[source,javascript]
----
db.user.createIndex(
{ "$**" : 1 },
{ "wildcardProjection" :
{ "userMetadata.age" : 0 }
}
)
----
====
Wildcard indexes can also be expressed by adding the annotation directly to the field.
Please note that `wildcardProjection` is not allowed on nested paths such as properties.
Projections on types annotated with `@WildcardIndexed` are omitted during index creation.
.Wildcard index on property
====
[source,java]
----
@Document
public class User {
private @Id String id;
@WildcardIndexed
private UserMetadata userMetadata;
}
----
[source,javascript]
----
db.user.createIndex({ "userMetadata.$**" : 1 }, {})
----
====
[[mapping-usage-indexes.text-index]]
=== Text Indexes
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:
.Example Text Index Usage
====
[source,java]
----
@Document(language = "spanish")
class SomeEntity {
@TextIndexed String foo;
@Language String lang;
Nested nested;
}
class Nested {
@TextIndexed(weight=5) String bar;
String roo;
}
----
====
[[mapping-usage-events]]
=== Mapping Framework Events
Events are fired throughout the lifecycle of the mapping process. This is described in the xref:mongodb/mapping/lifecycle-events.adoc[Lifecycle Events] section.
Declaring these beans in your Spring ApplicationContext causes them to be invoked whenever the event is dispatched.

15
src/main/antora/modules/ROOT/pages/mongodb/mapping/property-converters.adoc

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
[[mongo.property-converters]]
= Property Converters - Mapping specific fields
= Property Converters
While xref:mongodb/mapping/custom-conversions.adoc[type-based conversion] already offers ways to influence the conversion and representation of certain types within the target store, it has limitations when only certain values or properties of a particular type should be considered for conversion.
Property-based converters allow configuring conversion rules on a per-property basis, either declaratively (via `@ValueConverter`) or programmatically (by registering a `PropertyValueConverter` for a specific property).
@ -78,19 +78,10 @@ registrar.registerConverter(Person.class, Person::getSsn()) @@ -78,19 +78,10 @@ registrar.registerConverter(Person.class, Person::getSsn())
WARNING: Dot notation (such as `registerConverter(Person.class, "address.street", …)`) for nagivating across properties into subdocuments is *not* supported when registering converters.
[[mongo.property-converters.value-conversions]]
== MongoDB property value conversions
The preceding sections outlined the purpose an overall structure of `PropertyValueConverters`.
This section focuses on MongoDB specific aspects.
[[mongovalueconverter-and-mongoconversioncontext]]
=== MongoValueConverter and MongoConversionContext
`MongoValueConverter` offers a pre-typed `PropertyValueConverter` interface that uses `MongoConversionContext`.
TIP: `MongoValueConverter` offers a pre-typed `PropertyValueConverter` interface that uses `MongoConversionContext`.
[[mongocustomconversions-configuration]]
=== MongoCustomConversions configuration
== MongoCustomConversions configuration
By default, `MongoCustomConversions` can handle declarative value converters, depending on the configured `PropertyValueConverterFactory`.
`MongoConverterConfigurationAdapter` helps to set up programmatic value conversions or define the `PropertyValueConverterFactory` to be used.

Loading…
Cancel
Save