From 7c50f991ed7299f3e8dfec5cc567d1bac3ff3ecb Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 7 Sep 2023 10:59:00 +0200 Subject: [PATCH] Restructure documentation. Move examples into test source root to ensure proper compilation. Remove lingering asciidoc resources. Merge entity callbacks into lifecycle events. Add links from MongoDB overview. See: #4497 --- .../mongodb/example}/MongoApplication.java | 4 +- .../data/mongodb/example}/Person.java | 0 .../example}/ReactiveMongoApplication.java | 1 - .../modules/ROOT/assets/images/epub-cover.png | Bin 66019 -> 0 bytes .../modules/ROOT/assets/images/epub-cover.svg | 12 - src/main/antora/modules/ROOT/examples/example | 1 + src/main/antora/modules/ROOT/nav.adoc | 20 +- .../ROOT/pages/kotlin/object-mapping.adoc | 1 - .../antora/modules/ROOT/pages/mongodb.adoc | 23 +- .../ROOT/pages/mongodb/getting-started.adoc | 6 +- .../{mapping => }/lifecycle-events.adoc | 52 +- .../mongodb/mapping/custom-conversions.adoc | 2 +- .../mongodb/mapping/entity-callbacks.adoc | 45 - .../mapping-schema.adoc} | 0 .../ROOT/pages/mongodb/mapping/mapping.adoc | 18 +- .../ROOT/pages/mongodb/mongo-encryption.adoc | 6 +- .../mongodb/repositories/query-methods.adoc | 875 ++++++++++++++++++ .../repositories/repositories-collation.adoc | 69 -- .../repositories-index-hints.adoc | 20 - .../mongodb/repositories/repositories.adoc | 793 +--------------- .../template-collection-management.adoc | 2 +- .../ROOT/pages/mongodb/template-config.adoc | 8 +- .../mongodb/template-crud-operations.adoc | 50 +- .../pages/mongodb/template-id-handling.adoc | 42 - .../mongodb/template-query-operations.adoc | 87 +- .../pages/mongodb/template-query-options.adoc | 81 -- .../pages/repositories/core-concepts.adoc | 2 +- .../ROOT/pages/repositories/projections.adoc | 6 +- .../query-by-example.adoc | 6 +- src/main/asciidoc/images/epub-cover.png | Bin 66019 -> 0 bytes src/main/asciidoc/images/epub-cover.svg | 12 - src/main/asciidoc/images/jconsole.png | Bin 49294 -> 0 bytes 32 files changed, 1114 insertions(+), 1130 deletions(-) rename {src/main/antora/modules/ROOT/examples => spring-data-mongodb/src/test/java/org/springframework/data/mongodb/example}/MongoApplication.java (90%) rename {src/main/antora/modules/ROOT/examples => spring-data-mongodb/src/test/java/org/springframework/data/mongodb/example}/Person.java (100%) rename {src/main/antora/modules/ROOT/examples => spring-data-mongodb/src/test/java/org/springframework/data/mongodb/example}/ReactiveMongoApplication.java (95%) delete mode 100644 src/main/antora/modules/ROOT/assets/images/epub-cover.png delete mode 100644 src/main/antora/modules/ROOT/assets/images/epub-cover.svg create mode 120000 src/main/antora/modules/ROOT/examples/example delete mode 100644 src/main/antora/modules/ROOT/pages/kotlin/object-mapping.adoc rename src/main/antora/modules/ROOT/pages/mongodb/{mapping => }/lifecycle-events.adoc (64%) delete mode 100644 src/main/antora/modules/ROOT/pages/mongodb/mapping/entity-callbacks.adoc rename src/main/antora/modules/ROOT/pages/mongodb/{template-collection-schema.adoc => mapping/mapping-schema.adoc} (100%) create mode 100644 src/main/antora/modules/ROOT/pages/mongodb/repositories/query-methods.adoc delete mode 100644 src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories-collation.adoc delete mode 100644 src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories-index-hints.adoc delete mode 100644 src/main/antora/modules/ROOT/pages/mongodb/template-id-handling.adoc delete mode 100644 src/main/antora/modules/ROOT/pages/mongodb/template-query-options.adoc rename src/main/antora/modules/ROOT/pages/{mongodb => repositories}/query-by-example.adoc (86%) delete mode 100644 src/main/asciidoc/images/epub-cover.png delete mode 100644 src/main/asciidoc/images/epub-cover.svg delete mode 100644 src/main/asciidoc/images/jconsole.png diff --git a/src/main/antora/modules/ROOT/examples/MongoApplication.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/example/MongoApplication.java similarity index 90% rename from src/main/antora/modules/ROOT/examples/MongoApplication.java rename to spring-data-mongodb/src/test/java/org/springframework/data/mongodb/example/MongoApplication.java index b7cb8d3ff..ca6230f8b 100644 --- a/src/main/antora/modules/ROOT/examples/MongoApplication.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/example/MongoApplication.java @@ -16,12 +16,10 @@ // tag::file[] package org.springframework.data.mongodb.example; -import static org.springframework.data.mongodb.core.query.Criteria.where; -import static org.springframework.data.mongodb.core.query.Query.query; +import static org.springframework.data.mongodb.core.query.Criteria.*; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.query.Query; import com.mongodb.client.MongoClients; diff --git a/src/main/antora/modules/ROOT/examples/Person.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/example/Person.java similarity index 100% rename from src/main/antora/modules/ROOT/examples/Person.java rename to spring-data-mongodb/src/test/java/org/springframework/data/mongodb/example/Person.java diff --git a/src/main/antora/modules/ROOT/examples/ReactiveMongoApplication.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/example/ReactiveMongoApplication.java similarity index 95% rename from src/main/antora/modules/ROOT/examples/ReactiveMongoApplication.java rename to spring-data-mongodb/src/test/java/org/springframework/data/mongodb/example/ReactiveMongoApplication.java index cbb53c590..fbf4a2fa4 100644 --- a/src/main/antora/modules/ROOT/examples/ReactiveMongoApplication.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/example/ReactiveMongoApplication.java @@ -17,7 +17,6 @@ package org.springframework.data.mongodb.example; import static org.springframework.data.mongodb.core.query.Criteria.*; -import static org.springframework.data.mongodb.core.query.Query.*; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; diff --git a/src/main/antora/modules/ROOT/assets/images/epub-cover.png b/src/main/antora/modules/ROOT/assets/images/epub-cover.png deleted file mode 100644 index 7be1d08b3e38461536357ea31bde85587cbd0c2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66019 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

f$GBB>ixy9dlh?v&LNRiLF!Pt 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 - - - - Spring Data MongoDB - Reference Guide - Mark Pollack, Thomas Risberg, - Oliver Gierke, Costin Leau, - Jon Brisbin, Thomas Darimont, - Christoph Strobl, Mark Paluch, - Jay Bryant - diff --git a/src/main/antora/modules/ROOT/examples/example b/src/main/antora/modules/ROOT/examples/example new file mode 120000 index 000000000..3195fe72a --- /dev/null +++ b/src/main/antora/modules/ROOT/examples/example @@ -0,0 +1 @@ +../../../../../../spring-data-mongodb/src/test/java/org/springframework/data/mongodb/example \ No newline at end of file diff --git a/src/main/antora/modules/ROOT/nav.adoc b/src/main/antora/modules/ROOT/nav.adoc index 702566fdb..c5b207607 100644 --- a/src/main/antora/modules/ROOT/nav.adoc +++ b/src/main/antora/modules/ROOT/nav.adoc @@ -7,40 +7,40 @@ * xref:mongodb.adoc[] ** xref:mongodb/getting-started.adoc[] ** xref:mongodb/configuration.adoc[] + ** xref:mongodb/template-api.adoc[] *** xref:mongodb/template-config.adoc[] +*** xref:mongodb/template-collection-management.adoc[] *** xref:mongodb/template-crud-operations.adoc[] *** xref:mongodb/template-query-operations.adoc[] -**** xref:mongodb/template-query-options.adoc[] -*** xref:mongodb/template-document-count.adoc[] *** xref:mongodb/aggregation-framework.adoc[] -*** xref:mongodb/template-collection-management.adoc[] -**** xref:mongodb/template-collection-schema.adoc[] -*** xref:mongodb/template-gridfs.adoc[] +*** xref:mongodb/template-document-count.adoc[] + +** xref:mongodb/template-gridfs.adoc[] ** xref:mongodb/mapping/mapping.adoc[] +*** xref:mongodb/mapping/mapping-schema.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[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/lifecycle-events.adoc[] +** xref:mongodb/auditing.adoc[] ** xref:mongodb/client-session-transactions.adoc[] ** xref:mongodb/change-streams.adoc[] ** xref:mongodb/tailable-cursors.adoc[] ** xref:mongodb/sharding.adoc[] ** xref:mongodb/mongo-encryption.adoc[] -** xref:mongodb/auditing.adoc[] // Repository * xref:repositories.adoc[] ** xref:repositories/core-concepts.adoc[] ** xref:repositories/definition.adoc[] ** xref:mongodb/repositories/repositories.adoc[] -*** xref:mongodb/repositories/repositories-index-hints.adoc[] -*** xref:mongodb/repositories/repositories-collation.adoc[] ** xref:repositories/create-instances.adoc[] ** xref:repositories/query-methods-details.adoc[] +** xref:mongodb/repositories/query-methods.adoc[] ** xref:repositories/projections.adoc[] ** xref:repositories/custom-implementations.adoc[] ** xref:repositories/core-domain-events.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/kotlin/object-mapping.adoc b/src/main/antora/modules/ROOT/pages/kotlin/object-mapping.adoc deleted file mode 100644 index 76cab88e9..000000000 --- a/src/main/antora/modules/ROOT/pages/kotlin/object-mapping.adoc +++ /dev/null @@ -1 +0,0 @@ -// include::{commons}@data-commons::page$kotlin/object-mapping.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/mongodb.adoc b/src/main/antora/modules/ROOT/pages/mongodb.adoc index eebf9a914..de07ceb92 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb.adoc @@ -4,17 +4,18 @@ Spring Data support for MongoDB contains a wide range of features: -* Spring configuration support with Java-based `@Configuration` classes or an XML namespace for a Mongo driver instance and replica sets. -* `MongoTemplate` helper class that increases productivity when performing common Mongo operations. Includes integrated object mapping between documents and POJOs. -* Exception translation into Spring's portable Data Access Exception hierarchy. -* Feature-rich Object Mapping integrated with Spring's Conversion Service. -* Annotation-based mapping metadata that is extensible to support other metadata formats. -* Persistence and mapping lifecycle events. -* Java-based Query, Criteria, and Update DSLs. -* Automatic implementation of Repository interfaces, including support for custom finder methods. -* QueryDSL integration to support type-safe queries. -* Multi Document Transactions. -* GeoSpatial integration. +* xref:mongodb/template-config.adoc[Spring configuration support] with Java-based `@Configuration` classes or an XML namespace for a Mongo driver instance and replica sets. +* xref:mongodb/template-api.adoc[`MongoTemplate` helper class] that increases productivity when performing common Mongo operations. +Includes integrated object mapping between documents and POJOs. +* xref:mongodb/template-api.adoc#mongo-template.exception-translation[Exception translation] into Spring's portable Data Access Exception hierarchy. +* Feature-rich xref:mongodb/mapping/mapping.adoc[Object Mapping] integrated with Spring's Conversion Service. +* xref:mongodb/mapping/mapping.adoc#mapping-usage-annotations[Annotation-based mapping metadata] that is extensible to support other metadata formats. +* xref:mongodb/lifecycle-events.adoc[Persistence and mapping lifecycle events]. +* xref:mongodb/template-query-operations.adoc[Java-based Query, Criteria, and Update DSLs]. +* Automatic implementation of xref:repositories.adoc[Repository interfaces], including support for custom query methods. +* xref:mongodb/repositories/repositories.adoc#mongodb.repositories.queries.type-safe[QueryDSL integration] to support type-safe queries. +* xref:mongodb/client-session-transactions.adoc[Multi-Document Transactions]. +* xref:mongodb/template-query-operations.adoc#mongo.geo-json[GeoSpatial integration]. For most tasks, you should use `MongoTemplate` or the Repository support, which both leverage the rich mapping functionality. `MongoTemplate` is the place to look for accessing functionality such as incrementing counters or ad-hoc CRUD operations. diff --git a/src/main/antora/modules/ROOT/pages/mongodb/getting-started.adoc b/src/main/antora/modules/ROOT/pages/mongodb/getting-started.adoc index e12fdc2a4..eed3a95e3 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/getting-started.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb/getting-started.adoc @@ -19,7 +19,7 @@ Then you can create a `Person` class to persist: ==== [source,java] ---- -include::example$Person.java[tags=file] +include::example$example/Person.java[tags=file] ---- ==== @@ -31,14 +31,14 @@ Imperative:: + [source,java,indent=0,subs="verbatim,quotes",role="primary"] ---- -include::example$MongoApplication.java[tags=file] +include::example$example/MongoApplication.java[tags=file] ---- Reactive:: + [source,java,indent=0,subs="verbatim,quotes",role="secondary"] ---- -include::example$ReactiveMongoApplication.java[tags=file] +include::example$example/ReactiveMongoApplication.java[tags=file] ---- ====== diff --git a/src/main/antora/modules/ROOT/pages/mongodb/mapping/lifecycle-events.adoc b/src/main/antora/modules/ROOT/pages/mongodb/lifecycle-events.adoc similarity index 64% rename from src/main/antora/modules/ROOT/pages/mongodb/mapping/lifecycle-events.adoc rename to src/main/antora/modules/ROOT/pages/mongodb/lifecycle-events.adoc index 8050b50c6..d6c608b40 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/mapping/lifecycle-events.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb/lifecycle-events.adoc @@ -49,8 +49,58 @@ Declaring these beans in your Spring ApplicationContext causes them to be invoke * `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`. +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`. WARNING: Lifecycle events depend on an `ApplicationEventMulticaster`, which in case of the `SimpleApplicationEventMulticaster` can be configured with a `TaskExecutor`, and therefore gives no guarantees when an Event is processed. +include::{commons}@data-commons::page$entity-callbacks.adoc[leveloffset=+1] + +[[mongo.entity-callbacks]] +== Store specific EntityCallbacks + +Spring Data MongoDB uses the `EntityCallback` API for its auditing support and reacts on the following callbacks. + +.Supported Entity Callbacks +[%header,cols="4"] +|=== +| Callback +| Method +| Description +| Order + +| `ReactiveBeforeConvertCallback` +`BeforeConvertCallback` +| `onBeforeConvert(T entity, String collection)` +| Invoked before a domain object is converted to `org.bson.Document`. +| `Ordered.LOWEST_PRECEDENCE` + +| `ReactiveAfterConvertCallback` +`AfterConvertCallback` +| `onAfterConvert(T entity, org.bson.Document target, String collection)` +| Invoked after a domain object is loaded. + +Can modify the domain object after reading it from a `org.bson.Document`. +| `Ordered.LOWEST_PRECEDENCE` + +| `ReactiveAuditingEntityCallback` +`AuditingEntityCallback` +| `onBeforeConvert(Object entity, String collection)` +| Marks an auditable entity _created_ or _modified_ +| 100 + +| `ReactiveBeforeSaveCallback` +`BeforeSaveCallback` +| `onBeforeSave(T entity, org.bson.Document target, String collection)` +| Invoked before a domain object is saved. + +Can modify the target, to be persisted, `Document` containing all mapped entity information. +| `Ordered.LOWEST_PRECEDENCE` + +| `ReactiveAfterSaveCallback` +`AfterSaveCallback` +| `onAfterSave(T entity, org.bson.Document target, String collection)` +| Invoked before a domain object is saved. + +Can modify the domain object, to be returned after save, `Document` containing all mapped entity information. +| `Ordered.LOWEST_PRECEDENCE` + +|=== diff --git a/src/main/antora/modules/ROOT/pages/mongodb/mapping/custom-conversions.adoc b/src/main/antora/modules/ROOT/pages/mongodb/mapping/custom-conversions.adoc index 7fcc0fa14..c929fe2ad 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/mapping/custom-conversions.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb/mapping/custom-conversions.adoc @@ -30,7 +30,7 @@ public class Payment { "date" : ISODate("2019-04-03T12:11:01.870Z") <3> } ---- -<1> String _id_ values that represent a valid `ObjectId` are converted automatically. See xref:mongodb/template-id-handling.adoc#mongo-template.id-handling[How the `_id` Field is Handled in the Mapping Layer] +<1> String _id_ values that represent a valid `ObjectId` are converted automatically. See xref:mongodb/template-crud-operations.adoc#mongo-template.id-handling[How the `_id` Field is Handled in the Mapping Layer] for details. <2> The desired target type is explicitly defined as `Decimal128` which translates to `NumberDecimal`. Otherwise the `BigDecimal` value would have been truned into a `String`. diff --git a/src/main/antora/modules/ROOT/pages/mongodb/mapping/entity-callbacks.adoc b/src/main/antora/modules/ROOT/pages/mongodb/mapping/entity-callbacks.adoc deleted file mode 100644 index 3ae3cb86f..000000000 --- a/src/main/antora/modules/ROOT/pages/mongodb/mapping/entity-callbacks.adoc +++ /dev/null @@ -1,45 +0,0 @@ -include::{commons}@data-commons::page$entity-callbacks.adoc[] - -[[mongo.entity-callbacks]] -== Store specific EntityCallbacks - -Spring Data MongoDB uses the `EntityCallback` API for its auditing support and reacts on the following callbacks. - -.Supported Entity Callbacks -[%header,cols="4"] -|=== -| Callback -| Method -| Description -| Order - -| Reactive/BeforeConvertCallback -| `onBeforeConvert(T entity, String collection)` -| Invoked before a domain object is converted to `org.bson.Document`. -| `Ordered.LOWEST_PRECEDENCE` - -| Reactive/AfterConvertCallback -| `onAfterConvert(T entity, org.bson.Document target, String collection)` -| Invoked after a domain object is loaded. + -Can modify the domain object after reading it from a `org.bson.Document`. -| `Ordered.LOWEST_PRECEDENCE` - -| Reactive/AuditingEntityCallback -| `onBeforeConvert(Object entity, String collection)` -| Marks an auditable entity _created_ or _modified_ -| 100 - -| Reactive/BeforeSaveCallback -| `onBeforeSave(T entity, org.bson.Document target, String collection)` -| Invoked before a domain object is saved. + - Can modify the target, to be persisted, `Document` containing all mapped entity information. -| `Ordered.LOWEST_PRECEDENCE` - -| Reactive/AfterSaveCallback -| `onAfterSave(T entity, org.bson.Document target, String collection)` -| Invoked before a domain object is saved. + - Can modify the domain object, to be returned after save, `Document` containing all mapped entity information. -| `Ordered.LOWEST_PRECEDENCE` - -|=== - diff --git a/src/main/antora/modules/ROOT/pages/mongodb/template-collection-schema.adoc b/src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping-schema.adoc similarity index 100% rename from src/main/antora/modules/ROOT/pages/mongodb/template-collection-schema.adoc rename to src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping-schema.adoc diff --git a/src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping.adoc b/src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping.adoc index 4b0b7fb39..7d6db21b6 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb/mapping/mapping.adoc @@ -9,21 +9,26 @@ The `MappingMongoConverter` also lets you map objects to documents without provi This section describes the features of the `MappingMongoConverter`, including fundamentals, how to use conventions for mapping objects to documents and how to override those conventions with annotation-based mapping metadata. +include::{commons}@data-commons::page$object-mapping.adoc[leveloffset=+1] + [[mapping-conventions]] == Convention-based Mapping -`MappingMongoConverter` has a few conventions for mapping objects to documents when no additional mapping metadata is provided. The conventions are: +`MappingMongoConverter` has a few conventions for mapping objects to documents when no additional mapping metadata is provided. +The conventions are: -* The short Java class name is mapped to the collection name in the following manner. The class `com.bigbank.SavingsAccount` maps to the `savingsAccount` collection name. +* The short Java class name is mapped to the collection name in the following manner. +The class `com.bigbank.SavingsAccount` maps to the `savingsAccount` collection name. * All nested objects are stored as nested objects in the document and *not* as DBRefs. * The converter uses any Spring Converters registered with it to override the default mapping of object properties to document fields and values. -* The fields of an object are used to convert to and from fields in the document. Public `JavaBean` properties are not used. -* If you have a single non-zero-argument constructor whose constructor argument names match top-level field names of document, that constructor is used. Otherwise, the zero-argument constructor is used. If there is more than one non-zero-argument constructor, an exception will be thrown. +* The fields of an object are used to convert to and from fields in the document. +Public `JavaBean` properties are not used. +* If you have a single non-zero-argument constructor whose constructor argument names match top-level field names of document, that constructor is used.Otherwise, the zero-argument constructor is used.If there is more than one non-zero-argument constructor, an exception will be thrown. [[mapping.conventions.id-field]] === How the `_id` field is handled in the mapping layer. -MongoDB requires that you have an `_id` field for all documents. If you don't provide one the driver will assign a ObjectId with a generated value. The "_id" field can be of any type the, other than arrays, so long as it is unique. The driver naturally supports all primitive types and Dates. When using the `MappingMongoConverter` there are certain rules that govern how properties from the Java class is mapped to this `_id` field. +MongoDB requires that you have an `_id` field for all documents.If you don't provide one the driver will assign a ObjectId with a generated value.The "_id" field can be of any type the, other than arrays, so long as it is unique.The driver naturally supports all primitive types and Dates.When using the `MappingMongoConverter` there are certain rules that govern how properties from the Java class is mapped to this `_id` field. The following outlines what field will be mapped to the `_id` document field: @@ -569,6 +574,7 @@ Additional examples for using the `@PersistenceConstructor` annotation can be fo [[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. +Events are fired throughout the lifecycle of the mapping process. +This is described in the xref:mongodb/lifecycle-events.adoc[Lifecycle Events] section. Declaring these beans in your Spring ApplicationContext causes them to be invoked whenever the event is dispatched. diff --git a/src/main/antora/modules/ROOT/pages/mongodb/mongo-encryption.adoc b/src/main/antora/modules/ROOT/pages/mongodb/mongo-encryption.adoc index 6487f39ba..c24ec5ca7 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/mongo-encryption.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb/mongo-encryption.adoc @@ -15,9 +15,9 @@ Specific data types require deterministic encryption to preserve equality compar == Automatic Encryption MongoDB supports https://www.mongodb.com/docs/manual/core/csfle/[Client-Side Field Level Encryption] out of the box using the MongoDB driver with its Automatic Encryption feature. -Automatic Encryption requires a xref:mongodb/template-collection-schema.adoc[JSON Schema] that allows to perform encrypted read and write operations without the need to provide an explicit en-/decryption step. +Automatic Encryption requires a xref:mongodb/mapping/mapping-schema.adoc[JSON Schema] that allows to perform encrypted read and write operations without the need to provide an explicit en-/decryption step. -Please refer to the xref:mongodb/template-collection-schema.adoc#mongo.jsonSchema.encrypted-fields[JSON Schema] section for more information on defining a JSON Schema that holds encryption information. +Please refer to the xref:mongodb/mapping/mapping-schema.adoc#mongo.jsonSchema.encrypted-fields[JSON Schema] section for more information on defining a JSON Schema that holds encryption information. To make use of a the `MongoJsonSchema` it needs to be combined with `AutoEncryptionSettings` which can be done eg. via a `MongoClientSettingsBuilderCustomizer`. @@ -50,7 +50,7 @@ MongoClientSettingsBuilderCustomizer customizer(MappingContext mappingContext) { == Explicit Encryption Explicit encryption uses the MongoDB driver's encryption library (`org.mongodb:mongodb-crypt`) to perform encryption and decryption tasks. -The `@ExplicitEncrypted` annotation is a combination of the `@Encrypted` annotation used for xref:mongodb/template-collection-schema.adoc#mongo.jsonSchema.encrypted-fields[JSON Schema creation] and a xref:mongodb/mapping/property-converters.adoc[Property Converter]. +The `@ExplicitEncrypted` annotation is a combination of the `@Encrypted` annotation used for xref:mongodb/mapping/mapping-schema.adoc#mongo.jsonSchema.encrypted-fields[JSON Schema creation] and a xref:mongodb/mapping/property-converters.adoc[Property Converter]. In other words, `@ExplicitEncrypted` uses existing building blocks to combine them for simplified explicit encryption support. [NOTE] diff --git a/src/main/antora/modules/ROOT/pages/mongodb/repositories/query-methods.adoc b/src/main/antora/modules/ROOT/pages/mongodb/repositories/query-methods.adoc new file mode 100644 index 000000000..961e87c8d --- /dev/null +++ b/src/main/antora/modules/ROOT/pages/mongodb/repositories/query-methods.adoc @@ -0,0 +1,875 @@ +[[mongodb.repositories.queries]] += MongoDB-specific Query Methods + +Most of the data access operations you usually trigger on a repository result in a query being executed against the MongoDB databases. +Defining such a query is a matter of declaring a method on the repository interface, as the following example shows: + +.PersonRepository with query methods +[tabs] +====== +Imperative:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- +public interface PersonRepository extends PagingAndSortingRepository { + + List findByLastname(String lastname); <1> + + Page findByFirstname(String firstname, Pageable pageable); <2> + + Person findByShippingAddresses(Address address); <3> + + Person findFirstByLastname(String lastname); <4> + + Stream findAllBy(); <5> +} +---- +<1> The `findByLastname` method shows a query for all people with the given last name. +The query is derived by parsing the method name for constraints that can be concatenated with `And` and `Or`. +Thus, the method name results in a query expression of `{"lastname" : lastname}`. +<2> Applies pagination to a query. +You can equip your method signature with a `Pageable` parameter and let the method return a `Page` instance and Spring Data automatically pages the query accordingly. +<3> Shows that you can query based on properties that are not primitive types. +Throws `IncorrectResultSizeDataAccessException` if more than one match is found. +<4> Uses the `First` keyword to restrict the query to only the first result. +Unlike <3>, this method does not throw an exception if more than one match is found. +<5> Uses a Java 8 `Stream` that reads and converts individual elements while iterating the stream. + +Reactive:: ++ +==== +[source,java,indent=0,subs="verbatim,quotes",role="secondary"] +---- +public interface ReactivePersonRepository extends ReactiveSortingRepository { + + Flux findByFirstname(String firstname); <1> + + Flux findByFirstname(Publisher firstname); <2> + + Flux findByFirstnameOrderByLastname(String firstname, Pageable pageable); <3> + + Mono findByFirstnameAndLastname(String firstname, String lastname); <4> + + Mono findFirstByLastname(String lastname); <5> +} +---- +<1> The method shows a query for all people with the given `lastname`. The query is derived by parsing the method name for constraints that can be concatenated with `And` and `Or`. Thus, the method name results in a query expression of `{"lastname" : lastname}`. +<2> The method shows a query for all people with the given `firstname` once the `firstname` is emitted by the given `Publisher`. +<3> Use `Pageable` to pass offset and sorting parameters to the database. +<4> Find a single entity for the given criteria. It completes with `IncorrectResultSizeDataAccessException` on non-unique results. +<5> Unless <4>, the first entity is always emitted even if the query yields more result documents. + +WARNING: The `Page` return type (as in `Mono`) is not supported by reactive repositories. + +It is possible to use `Pageable` in derived finder methods, to pass on `sort`, `limit` and `offset` parameters to the query to reduce load and network traffic. +The returned `Flux` will only emit data within the declared range. + +[source,java] +---- +Pageable page = PageRequest.of(1, 10, Sort.by("lastname")); +Flux persons = repository.findByFirstnameOrderByLastname("luke", page); +---- +==== +====== + +NOTE: We do not support referring to parameters that are mapped as `DBRef` in the domain class. + +The following table shows the keywords that are supported for query methods: + +[cols="1,2,3",options="header"] +.Supported keywords for query methods +|=== +| Keyword +| Sample +| Logical result + +| `After` +| `findByBirthdateAfter(Date date)` +| `{"birthdate" : {"$gt" : date}}` + +| `GreaterThan` +| `findByAgeGreaterThan(int age)` +| `{"age" : {"$gt" : age}}` + +| `GreaterThanEqual` +| `findByAgeGreaterThanEqual(int age)` +| `{"age" : {"$gte" : age}}` + +| `Before` +| `findByBirthdateBefore(Date date)` +| `{"birthdate" : {"$lt" : date}}` + +| `LessThan` +| `findByAgeLessThan(int age)` +| `{"age" : {"$lt" : age}}` + +| `LessThanEqual` +| `findByAgeLessThanEqual(int age)` +| `{"age" : {"$lte" : age}}` + +| `Between` +| `findByAgeBetween(int from, int to)` + +`findByAgeBetween(Range range)` +| `{"age" : {"$gt" : from, "$lt" : to}}` + +lower / upper bounds (`$gt` / `$gte` & `$lt` / `$lte`) according to `Range` + +| `In` +| `findByAgeIn(Collection ages)` +| `{"age" : {"$in" : [ages...]}}` + +| `NotIn` +| `findByAgeNotIn(Collection ages)` +| `{"age" : {"$nin" : [ages...]}}` + +| `IsNotNull`, `NotNull` +| `findByFirstnameNotNull()` +| `{"firstname" : {"$ne" : null}}` + +| `IsNull`, `Null` +| `findByFirstnameNull()` +| `{"firstname" : null}` + +| `Like`, `StartingWith`, `EndingWith` +| `findByFirstnameLike(String name)` +| `{"firstname" : name} (name as regex)` + +| `NotLike`, `IsNotLike` +| `findByFirstnameNotLike(String name)` +| `{"firstname" : { "$not" : name }} (name as regex)` + +| `Containing` on String +| `findByFirstnameContaining(String name)` +| `{"firstname" : name} (name as regex)` + +| `NotContaining` on String +| `findByFirstnameNotContaining(String name)` +| `{"firstname" : { "$not" : name}} (name as regex)` + +| `Containing` on Collection +| `findByAddressesContaining(Address address)` +| `{"addresses" : { "$in" : address}}` + +| `NotContaining` on Collection +| `findByAddressesNotContaining(Address address)` +| `{"addresses" : { "$not" : { "$in" : address}}}` + +| `Regex` +| `findByFirstnameRegex(String firstname)` +| `{"firstname" : {"$regex" : firstname }}` + +| `(No keyword)` +| `findByFirstname(String name)` +| `{"firstname" : name}` + +| `Not` +| `findByFirstnameNot(String name)` +| `{"firstname" : {"$ne" : name}}` + +| `Near` +| `findByLocationNear(Point point)` +| `{"location" : {"$near" : [x,y]}}` + +| `Near` +| `findByLocationNear(Point point, Distance max)` +| `{"location" : {"$near" : [x,y], "$maxDistance" : max}}` + +| `Near` +| `findByLocationNear(Point point, Distance min, Distance max)` +| `{"location" : {"$near" : [x,y], "$minDistance" : min, "$maxDistance" : max}}` + +| `Within` +| `findByLocationWithin(Circle circle)` +| `{"location" : {"$geoWithin" : {"$center" : [ [x, y], distance]}}}` + +| `Within` +| `findByLocationWithin(Box box)` +| `{"location" : {"$geoWithin" : {"$box" : [ [x1, y1], x2, y2]}}}` + +| `IsTrue`, `True` +| `findByActiveIsTrue()` +| `{"active" : true}` + +| `IsFalse`, `False` +| `findByActiveIsFalse()` +| `{"active" : false}` + +| `Exists` +| `findByLocationExists(boolean exists)` +| `{"location" : {"$exists" : exists }}` + +| `IgnoreCase` +| `findByUsernameIgnoreCase(String username)` +| `{"username" : {"$regex" : "^username$", "$options" : "i" }}` +|=== + +NOTE: If the property criterion compares a document, the order of the fields and exact equality in the document matters. + +[[mongodb.repositories.queries.geo-spatial]] +== Geo-spatial Queries + +As you saw in the preceding table of keywords, a few keywords trigger geo-spatial operations within a MongoDB query. +The `Near` keyword allows some further modification, as the next few examples show. + +The following example shows how to define a `near` query that finds all persons with a given distance of a given point: + +.Advanced `Near` queries +[tabs] +====== +Imperative:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- +public interface PersonRepository extends MongoRepository { + + // { 'location' : { '$near' : [point.x, point.y], '$maxDistance' : distance}} + List findByLocationNear(Point location, Distance distance); +} +---- + +Reactive:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="secondary"] +---- +interface PersonRepository extends ReactiveMongoRepository { + + // { 'location' : { '$near' : [point.x, point.y], '$maxDistance' : distance}} + Flux findByLocationNear(Point location, Distance distance); +} +---- +====== + +Adding a `Distance` parameter to the query method allows restricting results to those within the given distance. +If the `Distance` was set up containing a `Metric`, we transparently use `$nearSphere` instead of `$code`, as the following example shows: + +.Using `Distance` with `Metrics` +==== +[source,java] +---- +Point point = new Point(43.7, 48.8); +Distance distance = new Distance(200, Metrics.KILOMETERS); +… = repository.findByLocationNear(point, distance); +// {'location' : {'$nearSphere' : [43.7, 48.8], '$maxDistance' : 0.03135711885774796}} +---- +==== + +NOTE: Reactive Geo-spatial repository queries support the domain type and `GeoResult` results within a reactive wrapper type. `GeoPage` and `GeoResults` are not supported as they contradict the deferred result approach with pre-calculating the average distance. However, you can still pass in a `Pageable` argument to page results yourself. + +Using a `Distance` with a `Metric` causes a `$nearSphere` (instead of a plain `$near`) clause to be added. +Beyond that, the actual distance gets calculated according to the `Metrics` used. + +(Note that `Metric` does not refer to metric units of measure. +It could be miles rather than kilometers. +Rather, `metric` refers to the concept of a system of measurement, regardless of which system you use.) + +NOTE: Using `@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)` on the target property forces usage of the `$nearSphere` operator. + +[[geo-near-queries]] +=== Geo-near Queries + +Spring Data MongoDb supports geo-near queries, as the following example shows: + +[tabs] +====== +Imperative:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- +public interface PersonRepository extends MongoRepository { + + // {'geoNear' : 'location', 'near' : [x, y] } + GeoResults findByLocationNear(Point location); + + // No metric: {'geoNear' : 'person', 'near' : [x, y], maxDistance : distance } + // Metric: {'geoNear' : 'person', 'near' : [x, y], 'maxDistance' : distance, + // 'distanceMultiplier' : metric.multiplier, 'spherical' : true } + GeoResults findByLocationNear(Point location, Distance distance); + + // Metric: {'geoNear' : 'person', 'near' : [x, y], 'minDistance' : min, + // 'maxDistance' : max, 'distanceMultiplier' : metric.multiplier, + // 'spherical' : true } + GeoResults findByLocationNear(Point location, Distance min, Distance max); + + // {'geoNear' : 'location', 'near' : [x, y] } + GeoResults findByLocationNear(Point location); +} +---- + +Reactive:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="secondary"] +---- +interface PersonRepository extends ReactiveMongoRepository { + + // {'geoNear' : 'location', 'near' : [x, y] } + Flux> findByLocationNear(Point location); + + // No metric: {'geoNear' : 'person', 'near' : [x, y], maxDistance : distance } + // Metric: {'geoNear' : 'person', 'near' : [x, y], 'maxDistance' : distance, + // 'distanceMultiplier' : metric.multiplier, 'spherical' : true } + Flux> findByLocationNear(Point location, Distance distance); + + // Metric: {'geoNear' : 'person', 'near' : [x, y], 'minDistance' : min, + // 'maxDistance' : max, 'distanceMultiplier' : metric.multiplier, + // 'spherical' : true } + Flux> findByLocationNear(Point location, Distance min, Distance max); + + // {'geoNear' : 'location', 'near' : [x, y] } + Flux> findByLocationNear(Point location); +} +---- +====== + +[[mongodb.repositories.queries.json-based]] +== JSON-based Query Methods and Field Restriction + +By adding the `org.springframework.data.mongodb.repository.Query` annotation to your repository query methods, you can specify a MongoDB JSON query string to use instead of having the query be derived from the method name, as the following example shows: + +[tabs] +====== +Imperative:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- +public interface PersonRepository extends MongoRepository { + + @Query("{ 'firstname' : ?0 }") + List findByThePersonsFirstname(String firstname); + +} +---- + +Reactive:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="secondary"] +---- +public interface PersonRepository extends ReactiveMongoRepository { + + @Query("{ 'firstname' : ?0 }") + Flux findByThePersonsFirstname(String firstname); + +} +---- +====== + +The `?0` placeholder lets you substitute the value from the method arguments into the JSON query string. + +NOTE: `String` parameter values are escaped during the binding process, which means that it is not possible to add MongoDB specific operators through the argument. + +You can also use the filter property to restrict the set of properties that is mapped into the Java object, as the following example shows: + +[tabs] +====== +Imperative:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- +public interface PersonRepository extends MongoRepository { + + @Query(value="{ 'firstname' : ?0 }", fields="{ 'firstname' : 1, 'lastname' : 1}") + List findByThePersonsFirstname(String firstname); + +} +---- + +Reactive:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="secondary"] +---- +public interface PersonRepository extends ReactiveMongoRepository { + + @Query(value="{ 'firstname' : ?0 }", fields="{ 'firstname' : 1, 'lastname' : 1}") + Flux findByThePersonsFirstname(String firstname); + +} +---- +====== + +The query in the preceding example returns only the `firstname`, `lastname` and `Id` properties of the `Person` objects. +The `age` property, a `java.lang.Integer`, is not set and its value is therefore null. + +[[mongodb.repositories.queries.sort]] +== Sorting Results + +MongoDB repositories allow various approaches to define sorting order. +Let's take a look at the following example: + +.Sorting Query Results +[tabs] +====== +Imperative:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- +public interface PersonRepository extends MongoRepository { + + List findByFirstnameSortByAgeDesc(String firstname); <1> + + List findByFirstname(String firstname, Sort sort); <2> + + @Query(sort = "{ age : -1 }") + List findByFirstname(String firstname); <3> + + @Query(sort = "{ age : -1 }") + List findByLastname(String lastname, Sort sort); <4> +} +---- +<1> Static sorting derived from method name. `SortByAgeDesc` results in `{ age : -1 }` for the sort parameter. +<2> Dynamic sorting using a method argument. +`Sort.by(DESC, "age")` creates `{ age : -1 }` for the sort parameter. +<3> Static sorting via `Query` annotation. +Sort parameter applied as stated in the `sort` attribute. +<4> Default sorting via `Query` annotation combined with dynamic one via a method argument. `Sort.unsorted()` +results in `{ age : -1 }`. +Using `Sort.by(ASC, "age")` overrides the defaults and creates `{ age : 1 }`. +`Sort.by +(ASC, "firstname")` alters the default and results in `{ age : -1, firstname : 1 }`. + +Reactive:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="secondary"] +---- +public interface PersonRepository extends ReactiveMongoRepository { + + Flux findByFirstnameSortByAgeDesc(String firstname); + + Flux findByFirstname(String firstname, Sort sort); + + @Query(sort = "{ age : -1 }") + Flux findByFirstname(String firstname); + + @Query(sort = "{ age : -1 }") + Flux findByLastname(String lastname, Sort sort); +} +---- +====== + +[[mongodb.repositories.queries.json-spel]] +== JSON-based Queries with SpEL Expressions + +Query strings and field definitions can be used together with SpEL expressions to create dynamic queries at runtime. +SpEL expressions can provide predicate values and can be used to extend predicates with subdocuments. + +Expressions expose method arguments through an array that contains all the arguments. +The following query uses `[0]` +to declare the predicate value for `lastname` (which is equivalent to the `?0` parameter binding): + +[tabs] +====== +Imperative:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- +public interface PersonRepository extends MongoRepository { + + @Query("{'lastname': ?#{[0]} }") + List findByQueryWithExpression(String param0); +} +---- + +Reactive:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="secondary"] +---- +public interface PersonRepository extends ReactiveMongoRepository { + + @Query("{'lastname': ?#{[0]} }") + Flux findByQueryWithExpression(String param0); +} +---- +====== + +Expressions can be used to invoke functions, evaluate conditionals, and construct values. +SpEL expressions used in conjunction with JSON reveal a side-effect, because Map-like declarations inside of SpEL read like JSON, as the following example shows: + +[tabs] +====== +Imperative:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- +public interface PersonRepository extends MongoRepository { + + @Query("{'id': ?#{ [0] ? {$exists :true} : [1] }}") + List findByQueryWithExpressionAndNestedObject(boolean param0, String param1); +} +---- + +Reactive:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="secondary"] +---- +public interface PersonRepository extends ReactiveMongoRepository { + + @Query("{'id': ?#{ [0] ? {$exists :true} : [1] }}") + Flux findByQueryWithExpressionAndNestedObject(boolean param0, String param1); +} +---- +====== + +WARNING: SpEL in query strings can be a powerful way to enhance queries. +However, they can also accept a broad range of unwanted arguments. +Make sure to sanitize strings before passing them to the query to avoid creation of vulnerabilities or unwanted changes to your query. + +Expression support is extensible through the Query SPI: `EvaluationContextExtension` & `ReactiveEvaluationContextExtension` +The Query SPI can contribute properties and functions and can customize the root object. +Extensions are retrieved from the application context at the time of SpEL evaluation when the query is built. +The following example shows how to use an evaluation context extension: + +[tabs] +====== +Imperative:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- +public class SampleEvaluationContextExtension extends EvaluationContextExtensionSupport { + + @Override + public String getExtensionId() { + return "security"; + } + + @Override + public Map getProperties() { + return Collections.singletonMap("principal", SecurityContextHolder.getCurrent().getPrincipal()); + } +} +---- + +Reactive:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="secondary"] +---- +public class SampleEvaluationContextExtension implements ReactiveEvaluationContextExtension { + + @Override + public String getExtensionId() { + return "security"; + } + + @Override + public Mono getExtension() { + return Mono.just(new EvaluationContextExtensionSupport() { ... }); + } +} +---- +====== + +NOTE: Bootstrapping `MongoRepositoryFactory` yourself is not application context-aware and requires further configuration to pick up Query SPI extensions. + +NOTE: Reactive query methods can make use of `org.springframework.data.spel.spi.ReactiveEvaluationContextExtension`. + +[[mongodb.repositories.queries.update]] +== Update Methods + +You can also use the keywords in the preceding table to create queries that identify matching documents for running updates on them. +The actual update action is defined by the `@Update` annotation on the method itself, as the following listing shows. +Note that the naming schema for derived queries starts with `find`. +Using `update` (as in `updateAllByLastname(...)`) is allowed only in combination with `@Query`. + +The update is applied to *all* matching documents and it is *not* possible to limit the scope by passing in a `Page` or by using any of the <>. +The return type can be either `void` or a _numeric_ type, such as `long`, to hold the number of modified documents. + +.Update Methods +==== +[source,java] +---- +public interface PersonRepository extends CrudRepository { + + @Update("{ '$inc' : { 'visits' : 1 } }") + long findAndIncrementVisitsByLastname(String lastname); <1> + + @Update("{ '$inc' : { 'visits' : ?1 } }") + void findAndIncrementVisitsByLastname(String lastname, int increment); <2> + + @Update("{ '$inc' : { 'visits' : ?#{[1]} } }") + long findAndIncrementVisitsUsingSpELByLastname(String lastname, int increment); <3> + + @Update(pipeline = {"{ '$set' : { 'visits' : { '$add' : [ '$visits', ?1 ] } } }"}) + void findAndIncrementVisitsViaPipelineByLastname(String lastname, int increment); <4> + + @Update("{ '$push' : { 'shippingAddresses' : ?1 } }") + long findAndPushShippingAddressByEmail(String email, Address address); <5> + + @Query("{ 'lastname' : ?0 }") + @Update("{ '$inc' : { 'visits' : ?1 } }") + void updateAllByLastname(String lastname, int increment); <6> +} +---- + +<1> The filter query for the update is derived from the method name. +The update is "`as is`" and does not bind any parameters. +<2> The actual increment value is defined by the `increment` method argument that is bound to the `?1` placeholder. +<3> Use the Spring Expression Language (SpEL) for parameter binding. +<4> Use the `pipeline` attribute to issue xref:mongodb/template-crud-operations.adoc#mongo-template.aggregation-update[aggregation pipeline updates]. +<5> The update may contain complex objects. +<6> Combine a xref:mongodb/repositories/repositories.adoc#mongodb.repositories.queries.json-based[string based query] with an update. +==== + +WARNING: Repository updates do not emit persistence nor mapping lifecycle events. + +[[mongodb.repositories.queries.delete]] +== Delete Methods + +The keywords in the preceding table can be used in conjunction with `delete…By` or `remove…By` to create queries that delete matching documents. + +.`Delete…By` Query +[tabs] +====== +Imperative:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- +public interface PersonRepository extends MongoRepository { + + List deleteByLastname(String lastname); <1> + + Long deletePersonByLastname(String lastname); <2> + + @Nullable + Person deleteSingleByLastname(String lastname); <3> + + Optional deleteByBirthdate(Date birthdate); <4> +} +---- +<1> Using a return type of `List` retrieves and returns all matching documents before actually deleting them. +<2> A numeric return type directly removes the matching documents, returning the total number of documents removed. +<3> A single domain type result retrieves and removes the first matching document. +<4> Same as in 3 but wrapped in an `Optional` type. + +Reactive:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="secondary"] +---- +public interface PersonRepository extends ReactiveMongoRepository { + + Flux deleteByLastname(String lastname); <1> + + Mono deletePersonByLastname(String lastname); <2> + + Mono deleteSingleByLastname(String lastname); <3> +} +---- +<1> Using a return type of `Flux` retrieves and returns all matching documents before actually deleting them. +<2> A numeric return type directly removes the matching documents, returning the total number of documents removed. +<3> A single domain type result retrieves and removes the first matching document. +====== + +[[mongodb.repositories.queries.aggregation]] +== Aggregation Methods + +The repository layer offers means to interact with xref:mongodb/aggregation-framework.adoc[the aggregation framework] via annotated repository query methods. +Similar to the xref:mongodb/repositories/repositories.adoc#mongodb.repositories.queries.json-based[JSON based queries], you can define a pipeline using the `org.springframework.data.mongodb.repository.Aggregation` annotation. +The definition may contain simple placeholders like `?0` as well as link:{springDocsUrl}/core.html#expressions[SpEL expressions] `?#{ … }`. + +.Aggregating Repository Method +==== +[source,java] +---- +public interface PersonRepository extends CrudRepository { + + @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") + List groupByLastnameAndFirstnames(); <1> + + @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") + List groupByLastnameAndFirstnames(Sort sort); <2> + + @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : ?0 } } }") + List groupByLastnameAnd(String property); <3> + + @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : ?0 } } }") + Slice groupByLastnameAnd(String property, Pageable page); <4> + + @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") + Stream groupByLastnameAndFirstnamesAsStream(); <5> + + @Aggregation("{ $group : { _id : null, total : { $sum : $age } } }") + SumValue sumAgeUsingValueWrapper(); <6> + + @Aggregation("{ $group : { _id : null, total : { $sum : $age } } }") + Long sumAge(); <7> + + @Aggregation("{ $group : { _id : null, total : { $sum : $age } } }") + AggregationResults sumAgeRaw(); <8> + + @Aggregation("{ '$project': { '_id' : '$lastname' } }") + List findAllLastnames(); <9> + + @Aggregation(pipeline = { + "{ $group : { _id : '$author', books: { $push: '$title' } } }", + "{ $out : 'authors' }" + }) + void groupAndOutSkippingOutput(); <10> +} +---- +[source,java] +---- +public class PersonAggregate { + + private @Id String lastname; <2> + private List names; + + public PersonAggregate(String lastname, List names) { + // ... + } + + // Getter / Setter omitted +} + +public class SumValue { + + private final Long total; <6> <8> + + public SumValue(Long total) { + // ... + } + + // Getter omitted +} +---- +<1> Aggregation pipeline to group first names by `lastname` in the `Person` collection returning these as `PersonAggregate`. +<2> If `Sort` argument is present, `$sort` is appended after the declared pipeline stages so that it only affects the order of the final results after having passed all other aggregation stages. +Therefore, the `Sort` properties are mapped against the methods return type `PersonAggregate` which turns `Sort.by("lastname")` into `{ $sort : { '_id', 1 } }` because `PersonAggregate.lastname` is annotated with `@Id`. +<3> Replaces `?0` with the given value for `property` for a dynamic aggregation pipeline. +<4> `$skip`, `$limit` and `$sort` can be passed on via a `Pageable` argument. Same as in <2>, the operators are appended to the pipeline definition. Methods accepting `Pageable` can return `Slice` for easier pagination. +<5> Aggregation methods can return `Stream` to consume results directly from an underlying cursor. Make sure to close the stream after consuming it to release the server-side cursor by either calling `close()` or through `try-with-resources`. +<6> Map the result of an aggregation returning a single `Document` to an instance of a desired `SumValue` target type. +<7> Aggregations resulting in single document holding just an accumulation result like e.g. `$sum` can be extracted directly from the result `Document`. +To gain more control, you might consider `AggregationResult` as method return type as shown in <7>. +<8> Obtain the raw `AggregationResults` mapped to the generic target wrapper type `SumValue` or `org.bson.Document`. +<9> Like in <6>, a single value can be directly obtained from multiple result ``Document``s. +<10> Skips the output of the `$out` stage when return type is `void`. +==== + +In some scenarios, aggregations might require additional options, such as a maximum run time, additional log comments, or the permission to temporarily write data to disk. +Use the `@Meta` annotation to set those options via `maxExecutionTimeMs`, `comment` or `allowDiskUse`. + +[source,java] +---- +interface PersonRepository extends CrudRepository { + + @Meta(allowDiskUse = true) + @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") + List groupByLastnameAndFirstnames(); +} +---- + +Or use `@Meta` to create your own annotation as shown in the sample below. + +[source,java] +---- +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD }) +@Meta(allowDiskUse = true) +@interface AllowDiskUse { } + +interface PersonRepository extends CrudRepository { + + @AllowDiskUse + @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") + List groupByLastnameAndFirstnames(); +} +---- + +[NOTE] +==== +Simple-type single-result inspects the returned `Document` and checks for the following: + +. Only one entry in the document, return it. +. Two entries, one is the `_id` value. Return the other. +. Return for the first value assignable to the return type. +. Throw an exception if none of the above is applicable. +==== + +WARNING: The `Page` return type is not supported for repository methods using `@Aggregation`. However, you can use a +`Pageable` argument to add `$skip`, `$limit` and `$sort` to the pipeline and let the method return `Slice`. + +[[mongodb.repositories.index-hint]] +== Index Hints + +The `@Hint` annotation allows to override MongoDB's default index selection and forces the database to use the specified index instead. + +.Example of index hints +==== +[source,java] +---- +@Hint("lastname-idx") <1> +List findByLastname(String lastname); + +@Query(value = "{ 'firstname' : ?0 }", hint = "firstname-idx") <2> +List findByFirstname(String firstname); +---- +<1> Use the index with name `lastname-idx`. +<2> The `@Query` annotation defines the `hint` alias which is equivalent to adding the `@Hint` annotation. +==== + +For more information about index creation please refer to the xref:mongodb/template-collection-management.adoc[Collection Management] section. + +[[mongo.repositories.collation]] +== Repository Collation Support + +Next to the xref:mongodb/collation.adoc[general Collation Support] repositories allow to define the collation for various operations. + +==== +[source,java] +---- +public interface PersonRepository extends MongoRepository { + + @Query(collation = "en_US") <1> + List findByFirstname(String firstname); + + @Query(collation = "{ 'locale' : 'en_US' }") <2> + List findPersonByFirstname(String firstname); + + @Query(collation = "?1") <3> + List findByFirstname(String firstname, Object collation); + + @Query(collation = "{ 'locale' : '?1' }") <4> + List findByFirstname(String firstname, String collation); + + List findByFirstname(String firstname, Collation collation); <5> + + @Query(collation = "{ 'locale' : 'en_US' }") + List findByFirstname(String firstname, @Nullable Collation collation); <6> +} +---- +<1> Static collation definition resulting in `{ 'locale' : 'en_US' }`. +<2> Static collation definition resulting in `{ 'locale' : 'en_US' }`. +<3> Dynamic collation depending on 2nd method argument. Allowed types include `String` (eg. 'en_US'), `Locacle` (eg. Locacle.US) +and `Document` (eg. new Document("locale", "en_US")) +<4> Dynamic collation depending on 2nd method argument. +<5> Apply the `Collation` method parameter to the query. +<6> The `Collation` method parameter overrides the default `collation` from `@Query` if not null. + +NOTE: In case you enabled the automatic index creation for repository finder methods a potential static collation definition, +as shown in (1) and (2), will be included when creating the index. + +TIP: The most specifc `Collation` outrules potentially defined others. Which means Method argument over query method annotation over domain type annotation. +==== + +To streamline usage of collation attributes throughout the codebase it is also possible to use the `@Collation` annotation, which serves as a meta annotation for the ones mentioned above. +The same rules and locations apply, plus, direct usage of `@Collation` supersedes any collation values defined on `@Query` and other annotations. +Which means, if a collation is declared via `@Query` and additionally via `@Collation`, then the one from `@Collation` is picked. + +.Using `@Collation` +==== +[source,java] +---- +@Collation("en_US") <1> +class Game { + // ... +} + +interface GameRepository extends Repository { + + @Collation("en_GB") <2> + List findByTitle(String title); + + @Collation("de_AT") <3> + @Query(collation="en_GB") + List findByDescriptionContaining(String keyword); +} +---- +<1> Instead of `@Document(collation=...)`. +<2> Instead of `@Query(collation=...)`. +<3> Favors `@Collation` over meta usage. +==== diff --git a/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories-collation.adoc b/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories-collation.adoc deleted file mode 100644 index ebf0589eb..000000000 --- a/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories-collation.adoc +++ /dev/null @@ -1,69 +0,0 @@ -[[mongo.repositories.collation]] -= Repository Collation Support - -Next to the xref:mongodb/collation.adoc[general Collation Support] repositories allow to define the collation for various operations. - -==== -[source,java] ----- -public interface PersonRepository extends MongoRepository { - - @Query(collation = "en_US") <1> - List findByFirstname(String firstname); - - @Query(collation = "{ 'locale' : 'en_US' }") <2> - List findPersonByFirstname(String firstname); - - @Query(collation = "?1") <3> - List findByFirstname(String firstname, Object collation); - - @Query(collation = "{ 'locale' : '?1' }") <4> - List findByFirstname(String firstname, String collation); - - List findByFirstname(String firstname, Collation collation); <5> - - @Query(collation = "{ 'locale' : 'en_US' }") - List findByFirstname(String firstname, @Nullable Collation collation); <6> -} ----- -<1> Static collation definition resulting in `{ 'locale' : 'en_US' }`. -<2> Static collation definition resulting in `{ 'locale' : 'en_US' }`. -<3> Dynamic collation depending on 2nd method argument. Allowed types include `String` (eg. 'en_US'), `Locacle` (eg. Locacle.US) -and `Document` (eg. new Document("locale", "en_US")) -<4> Dynamic collation depending on 2nd method argument. -<5> Apply the `Collation` method parameter to the query. -<6> The `Collation` method parameter overrides the default `collation` from `@Query` if not null. - -NOTE: In case you enabled the automatic index creation for repository finder methods a potential static collation definition, -as shown in (1) and (2), will be included when creating the index. - -TIP: The most specifc `Collation` outrules potentially defined others. Which means Method argument over query method annotation over domain type annotation. -==== - -To streamline usage of collation attributes throughout the codebase it is also possible to use the `@Collation` annotation, which serves as a meta annotation for the ones mentioned above. -The same rules and locations apply, plus, direct usage of `@Collation` supersedes any collation values defined on `@Query` and other annotations. -Which means, if a collation is declared via `@Query` and additionally via `@Collation`, then the one from `@Collation` is picked. - -.Using `@Collation` -==== -[source,java] ----- -@Collation("en_US") <1> -class Game { - // ... -} - -interface GameRepository extends Repository { - - @Collation("en_GB") <2> - List findByTitle(String title); - - @Collation("de_AT") <3> - @Query(collation="en_GB") - List findByDescriptionContaining(String keyword); -} ----- -<1> Instead of `@Document(collation=...)`. -<2> Instead of `@Query(collation=...)`. -<3> Favors `@Collation` over meta usage. -==== diff --git a/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories-index-hints.adoc b/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories-index-hints.adoc deleted file mode 100644 index 555bbf96e..000000000 --- a/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories-index-hints.adoc +++ /dev/null @@ -1,20 +0,0 @@ -[[mongodb.repositories.index-hint]] -= Index Hints - -The `@Hint` annotation allows to override MongoDB's default index selection and forces the database to use the specified index instead. - -.Example of index hints -==== -[source,java] ----- -@Hint("lastname-idx") <1> -List findByLastname(String lastname); - -@Query(value = "{ 'firstname' : ?0 }", hint = "firstname-idx") <2> -List findByFirstname(String firstname); ----- -<1> Use the index with name `lastname-idx`. -<2> The `@Query` annotation defines the `hint` alias which is equivalent to adding the `@Hint` annotation. -==== - -For more information about index creation please refer to the xref:mongodb/template-collection-management.adoc[Collection Management] section. diff --git a/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories.adoc b/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories.adoc index 97149d3e6..ae8d68dd6 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories.adoc @@ -31,7 +31,7 @@ public class Person { Note that the domain type shown in the preceding example has a property named `id` of type `String`.The default serialization mechanism used in `MongoTemplate` (which backs the repository support) regards properties named `id` as the document ID. Currently, we support `String`, `ObjectId`, and `BigInteger` as ID types. -Please see xref:mongodb/template-id-handling.adoc#mongo-template.id-handling[ID mapping] for more information about on how the `id` field is handled in the mapping layer. +Please see xref:mongodb/template-crud-operations.adoc#mongo-template.id-handling[ID mapping] for more information about on how the `id` field is handled in the mapping layer. Now that we have a domain object, we can define an interface that uses it, as follows: @@ -212,568 +212,8 @@ The preceding example creates an application context with Spring's unit test sup Inside the test method, we use the repository to query the datastore. We hand the repository a `PageRequest` instance that requests the first page of `Person` objects at a page size of 10. -[[mongodb.repositories.queries]] -== Query Methods - -Most of the data access operations you usually trigger on a repository result in a query being executed against the MongoDB databases. -Defining such a query is a matter of declaring a method on the repository interface, as the following example shows: - -.PersonRepository with query methods -[tabs] -====== -Imperative:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="primary"] ----- -public interface PersonRepository extends PagingAndSortingRepository { - - List findByLastname(String lastname); <1> - - Page findByFirstname(String firstname, Pageable pageable); <2> - - Person findByShippingAddresses(Address address); <3> - - Person findFirstByLastname(String lastname); <4> - - Stream findAllBy(); <5> -} ----- -<1> The `findByLastname` method shows a query for all people with the given last name. -The query is derived by parsing the method name for constraints that can be concatenated with `And` and `Or`. -Thus, the method name results in a query expression of `{"lastname" : lastname}`. -<2> Applies pagination to a query. -You can equip your method signature with a `Pageable` parameter and let the method return a `Page` instance and Spring Data automatically pages the query accordingly. -<3> Shows that you can query based on properties that are not primitive types. -Throws `IncorrectResultSizeDataAccessException` if more than one match is found. -<4> Uses the `First` keyword to restrict the query to only the first result. -Unlike <3>, this method does not throw an exception if more than one match is found. -<5> Uses a Java 8 `Stream` that reads and converts individual elements while iterating the stream. - -Reactive:: -+ -==== -[source,java,indent=0,subs="verbatim,quotes",role="secondary"] ----- -public interface ReactivePersonRepository extends ReactiveSortingRepository { - - Flux findByFirstname(String firstname); <1> - - Flux findByFirstname(Publisher firstname); <2> - - Flux findByFirstnameOrderByLastname(String firstname, Pageable pageable); <3> - - Mono findByFirstnameAndLastname(String firstname, String lastname); <4> - - Mono findFirstByLastname(String lastname); <5> -} ----- -<1> The method shows a query for all people with the given `lastname`. The query is derived by parsing the method name for constraints that can be concatenated with `And` and `Or`. Thus, the method name results in a query expression of `{"lastname" : lastname}`. -<2> The method shows a query for all people with the given `firstname` once the `firstname` is emitted by the given `Publisher`. -<3> Use `Pageable` to pass offset and sorting parameters to the database. -<4> Find a single entity for the given criteria. It completes with `IncorrectResultSizeDataAccessException` on non-unique results. -<5> Unless <4>, the first entity is always emitted even if the query yields more result documents. - -WARNING: The `Page` return type (as in `Mono`) is not supported by reactive repositories. - -It is possible to use `Pageable` in derived finder methods, to pass on `sort`, `limit` and `offset` parameters to the query to reduce load and network traffic. -The returned `Flux` will only emit data within the declared range. - -[source,java] ----- -Pageable page = PageRequest.of(1, 10, Sort.by("lastname")); -Flux persons = repository.findByFirstnameOrderByLastname("luke", page); ----- -==== -====== - -NOTE: We do not support referring to parameters that are mapped as `DBRef` in the domain class. - -The following table shows the keywords that are supported for query methods: - -[cols="1,2,3",options="header"] -.Supported keywords for query methods -|=== -| Keyword -| Sample -| Logical result - -| `After` -| `findByBirthdateAfter(Date date)` -| `{"birthdate" : {"$gt" : date}}` - -| `GreaterThan` -| `findByAgeGreaterThan(int age)` -| `{"age" : {"$gt" : age}}` - -| `GreaterThanEqual` -| `findByAgeGreaterThanEqual(int age)` -| `{"age" : {"$gte" : age}}` - -| `Before` -| `findByBirthdateBefore(Date date)` -| `{"birthdate" : {"$lt" : date}}` - -| `LessThan` -| `findByAgeLessThan(int age)` -| `{"age" : {"$lt" : age}}` - -| `LessThanEqual` -| `findByAgeLessThanEqual(int age)` -| `{"age" : {"$lte" : age}}` - -| `Between` -| `findByAgeBetween(int from, int to)` + -`findByAgeBetween(Range range)` -| `{"age" : {"$gt" : from, "$lt" : to}}` + -lower / upper bounds (`$gt` / `$gte` & `$lt` / `$lte`) according to `Range` - -| `In` -| `findByAgeIn(Collection ages)` -| `{"age" : {"$in" : [ages...]}}` - -| `NotIn` -| `findByAgeNotIn(Collection ages)` -| `{"age" : {"$nin" : [ages...]}}` - -| `IsNotNull`, `NotNull` -| `findByFirstnameNotNull()` -| `{"firstname" : {"$ne" : null}}` - -| `IsNull`, `Null` -| `findByFirstnameNull()` -| `{"firstname" : null}` - -| `Like`, `StartingWith`, `EndingWith` -| `findByFirstnameLike(String name)` -| `{"firstname" : name} (name as regex)` - -| `NotLike`, `IsNotLike` -| `findByFirstnameNotLike(String name)` -| `{"firstname" : { "$not" : name }} (name as regex)` - -| `Containing` on String -| `findByFirstnameContaining(String name)` -| `{"firstname" : name} (name as regex)` - -| `NotContaining` on String -| `findByFirstnameNotContaining(String name)` -| `{"firstname" : { "$not" : name}} (name as regex)` - -| `Containing` on Collection -| `findByAddressesContaining(Address address)` -| `{"addresses" : { "$in" : address}}` - -| `NotContaining` on Collection -| `findByAddressesNotContaining(Address address)` -| `{"addresses" : { "$not" : { "$in" : address}}}` - -| `Regex` -| `findByFirstnameRegex(String firstname)` -| `{"firstname" : {"$regex" : firstname }}` - -| `(No keyword)` -| `findByFirstname(String name)` -| `{"firstname" : name}` - -| `Not` -| `findByFirstnameNot(String name)` -| `{"firstname" : {"$ne" : name}}` - -| `Near` -| `findByLocationNear(Point point)` -| `{"location" : {"$near" : [x,y]}}` - -| `Near` -| `findByLocationNear(Point point, Distance max)` -| `{"location" : {"$near" : [x,y], "$maxDistance" : max}}` - -| `Near` -| `findByLocationNear(Point point, Distance min, Distance max)` -| `{"location" : {"$near" : [x,y], "$minDistance" : min, "$maxDistance" : max}}` - -| `Within` -| `findByLocationWithin(Circle circle)` -| `{"location" : {"$geoWithin" : {"$center" : [ [x, y], distance]}}}` - -| `Within` -| `findByLocationWithin(Box box)` -| `{"location" : {"$geoWithin" : {"$box" : [ [x1, y1], x2, y2]}}}` - -| `IsTrue`, `True` -| `findByActiveIsTrue()` -| `{"active" : true}` - -| `IsFalse`, `False` -| `findByActiveIsFalse()` -| `{"active" : false}` - -| `Exists` -| `findByLocationExists(boolean exists)` -| `{"location" : {"$exists" : exists }}` - -| `IgnoreCase` -| `findByUsernameIgnoreCase(String username)` -| `{"username" : {"$regex" : "^username$", "$options" : "i" }}` -|=== - -NOTE: If the property criterion compares a document, the order of the fields and exact equality in the document matters. - -[[mongodb.repositories.queries.geo-spatial]] -=== Geo-spatial Repository Queries - -As you saw in the preceding table of keywords, a few keywords trigger geo-spatial operations within a MongoDB query. -The `Near` keyword allows some further modification, as the next few examples show. - -The following example shows how to define a `near` query that finds all persons with a given distance of a given point: - -.Advanced `Near` queries -[tabs] -====== -Imperative:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="primary"] ----- -public interface PersonRepository extends MongoRepository { - - // { 'location' : { '$near' : [point.x, point.y], '$maxDistance' : distance}} - List findByLocationNear(Point location, Distance distance); -} ----- - -Reactive:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="secondary"] ----- -interface PersonRepository extends ReactiveMongoRepository { - - // { 'location' : { '$near' : [point.x, point.y], '$maxDistance' : distance}} - Flux findByLocationNear(Point location, Distance distance); -} ----- -====== - -Adding a `Distance` parameter to the query method allows restricting results to those within the given distance. -If the `Distance` was set up containing a `Metric`, we transparently use `$nearSphere` instead of `$code`, as the following example shows: - -.Using `Distance` with `Metrics` -==== -[source,java] ----- -Point point = new Point(43.7, 48.8); -Distance distance = new Distance(200, Metrics.KILOMETERS); -… = repository.findByLocationNear(point, distance); -// {'location' : {'$nearSphere' : [43.7, 48.8], '$maxDistance' : 0.03135711885774796}} ----- -==== - -NOTE: Reactive Geo-spatial repository queries support the domain type and `GeoResult` results within a reactive wrapper type. `GeoPage` and `GeoResults` are not supported as they contradict the deferred result approach with pre-calculating the average distance. However, you can still pass in a `Pageable` argument to page results yourself. - -Using a `Distance` with a `Metric` causes a `$nearSphere` (instead of a plain `$near`) clause to be added. -Beyond that, the actual distance gets calculated according to the `Metrics` used. - -(Note that `Metric` does not refer to metric units of measure. -It could be miles rather than kilometers. -Rather, `metric` refers to the concept of a system of measurement, regardless of which system you use.) - -NOTE: Using `@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)` on the target property forces usage of the `$nearSphere` operator. - -[[geo-near-queries]] -==== Geo-near Queries - -Spring Data MongoDb supports geo-near queries, as the following example shows: - -[tabs] -====== -Imperative:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="primary"] ----- -public interface PersonRepository extends MongoRepository { - - // {'geoNear' : 'location', 'near' : [x, y] } - GeoResults findByLocationNear(Point location); - - // No metric: {'geoNear' : 'person', 'near' : [x, y], maxDistance : distance } - // Metric: {'geoNear' : 'person', 'near' : [x, y], 'maxDistance' : distance, - // 'distanceMultiplier' : metric.multiplier, 'spherical' : true } - GeoResults findByLocationNear(Point location, Distance distance); - - // Metric: {'geoNear' : 'person', 'near' : [x, y], 'minDistance' : min, - // 'maxDistance' : max, 'distanceMultiplier' : metric.multiplier, - // 'spherical' : true } - GeoResults findByLocationNear(Point location, Distance min, Distance max); - - // {'geoNear' : 'location', 'near' : [x, y] } - GeoResults findByLocationNear(Point location); -} ----- - -Reactive:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="secondary"] ----- -interface PersonRepository extends ReactiveMongoRepository { - - // {'geoNear' : 'location', 'near' : [x, y] } - Flux> findByLocationNear(Point location); - - // No metric: {'geoNear' : 'person', 'near' : [x, y], maxDistance : distance } - // Metric: {'geoNear' : 'person', 'near' : [x, y], 'maxDistance' : distance, - // 'distanceMultiplier' : metric.multiplier, 'spherical' : true } - Flux> findByLocationNear(Point location, Distance distance); - - // Metric: {'geoNear' : 'person', 'near' : [x, y], 'minDistance' : min, - // 'maxDistance' : max, 'distanceMultiplier' : metric.multiplier, - // 'spherical' : true } - Flux> findByLocationNear(Point location, Distance min, Distance max); - - // {'geoNear' : 'location', 'near' : [x, y] } - Flux> findByLocationNear(Point location); -} ----- -====== - -[[mongodb.repositories.queries.json-based]] -=== MongoDB JSON-based Query Methods and Field Restriction - -By adding the `org.springframework.data.mongodb.repository.Query` annotation to your repository query methods, you can specify a MongoDB JSON query string to use instead of having the query be derived from the method name, as the following example shows: - -[tabs] -====== -Imperative:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="primary"] ----- -public interface PersonRepository extends MongoRepository { - - @Query("{ 'firstname' : ?0 }") - List findByThePersonsFirstname(String firstname); - -} ----- - -Reactive:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="secondary"] ----- -public interface PersonRepository extends ReactiveMongoRepository { - - @Query("{ 'firstname' : ?0 }") - Flux findByThePersonsFirstname(String firstname); - -} ----- -====== - -The `?0` placeholder lets you substitute the value from the method arguments into the JSON query string. - -NOTE: `String` parameter values are escaped during the binding process, which means that it is not possible to add MongoDB specific operators through the argument. - -You can also use the filter property to restrict the set of properties that is mapped into the Java object, as the following example shows: - -[tabs] -====== -Imperative:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="primary"] ----- -public interface PersonRepository extends MongoRepository { - - @Query(value="{ 'firstname' : ?0 }", fields="{ 'firstname' : 1, 'lastname' : 1}") - List findByThePersonsFirstname(String firstname); - -} ----- - -Reactive:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="secondary"] ----- -public interface PersonRepository extends ReactiveMongoRepository { - - @Query(value="{ 'firstname' : ?0 }", fields="{ 'firstname' : 1, 'lastname' : 1}") - Flux findByThePersonsFirstname(String firstname); - -} ----- -====== - -The query in the preceding example returns only the `firstname`, `lastname` and `Id` properties of the `Person` objects. -The `age` property, a `java.lang.Integer`, is not set and its value is therefore null. - -[[mongodb.repositories.queries.sort]] -=== Sorting Query Method results - -MongoDB repositories allow various approaches to define sorting order. -Let's take a look at the following example: - -.Sorting Query Results -[tabs] -====== -Imperative:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="primary"] ----- -public interface PersonRepository extends MongoRepository { - - List findByFirstnameSortByAgeDesc(String firstname); <1> - - List findByFirstname(String firstname, Sort sort); <2> - - @Query(sort = "{ age : -1 }") - List findByFirstname(String firstname); <3> - - @Query(sort = "{ age : -1 }") - List findByLastname(String lastname, Sort sort); <4> -} ----- -<1> Static sorting derived from method name. `SortByAgeDesc` results in `{ age : -1 }` for the sort parameter. -<2> Dynamic sorting using a method argument. -`Sort.by(DESC, "age")` creates `{ age : -1 }` for the sort parameter. -<3> Static sorting via `Query` annotation. -Sort parameter applied as stated in the `sort` attribute. -<4> Default sorting via `Query` annotation combined with dynamic one via a method argument. `Sort.unsorted()` -results in `{ age : -1 }`. -Using `Sort.by(ASC, "age")` overrides the defaults and creates `{ age : 1 }`. -`Sort.by -(ASC, "firstname")` alters the default and results in `{ age : -1, firstname : 1 }`. - -Reactive:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="secondary"] ----- -public interface PersonRepository extends ReactiveMongoRepository { - - Flux findByFirstnameSortByAgeDesc(String firstname); - - Flux findByFirstname(String firstname, Sort sort); - - @Query(sort = "{ age : -1 }") - Flux findByFirstname(String firstname); - - @Query(sort = "{ age : -1 }") - Flux findByLastname(String lastname, Sort sort); -} ----- -====== - -[[mongodb.repositories.queries.json-spel]] -=== JSON-based Queries with SpEL Expressions - -Query strings and field definitions can be used together with SpEL expressions to create dynamic queries at runtime. -SpEL expressions can provide predicate values and can be used to extend predicates with subdocuments. - -Expressions expose method arguments through an array that contains all the arguments. -The following query uses `[0]` -to declare the predicate value for `lastname` (which is equivalent to the `?0` parameter binding): - -[tabs] -====== -Imperative:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="primary"] ----- -public interface PersonRepository extends MongoRepository { - - @Query("{'lastname': ?#{[0]} }") - List findByQueryWithExpression(String param0); -} ----- - -Reactive:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="secondary"] ----- -public interface PersonRepository extends ReactiveMongoRepository { - - @Query("{'lastname': ?#{[0]} }") - Flux findByQueryWithExpression(String param0); -} ----- -====== - -Expressions can be used to invoke functions, evaluate conditionals, and construct values. -SpEL expressions used in conjunction with JSON reveal a side-effect, because Map-like declarations inside of SpEL read like JSON, as the following example shows: - -[tabs] -====== -Imperative:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="primary"] ----- -public interface PersonRepository extends MongoRepository { - - @Query("{'id': ?#{ [0] ? {$exists :true} : [1] }}") - List findByQueryWithExpressionAndNestedObject(boolean param0, String param1); -} ----- - -Reactive:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="secondary"] ----- -public interface PersonRepository extends ReactiveMongoRepository { - - @Query("{'id': ?#{ [0] ? {$exists :true} : [1] }}") - Flux findByQueryWithExpressionAndNestedObject(boolean param0, String param1); -} ----- -====== - -WARNING: SpEL in query strings can be a powerful way to enhance queries. -However, they can also accept a broad range of unwanted arguments. -Make sure to sanitize strings before passing them to the query to avoid creation of vulnerabilities or unwanted changes to your query. - -Expression support is extensible through the Query SPI: `EvaluationContextExtension` & `ReactiveEvaluationContextExtension` -The Query SPI can contribute properties and functions and can customize the root object. -Extensions are retrieved from the application context at the time of SpEL evaluation when the query is built. -The following example shows how to use an evaluation context extension: - -[tabs] -====== -Imperative:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="primary"] ----- -public class SampleEvaluationContextExtension extends EvaluationContextExtensionSupport { - - @Override - public String getExtensionId() { - return "security"; - } - - @Override - public Map getProperties() { - return Collections.singletonMap("principal", SecurityContextHolder.getCurrent().getPrincipal()); - } -} ----- - -Reactive:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="secondary"] ----- -public class SampleEvaluationContextExtension implements ReactiveEvaluationContextExtension { - - @Override - public String getExtensionId() { - return "security"; - } - - @Override - public Mono getExtension() { - return Mono.just(new EvaluationContextExtensionSupport() { ... }); - } -} ----- -====== - -NOTE: Bootstrapping `MongoRepositoryFactory` yourself is not application context-aware and requires further configuration to pick up Query SPI extensions. - -NOTE: Reactive query methods can make use of `org.springframework.data.spel.spi.ReactiveEvaluationContextExtension`. - [[mongodb.repositories.queries.type-safe]] -=== Type-safe Query Methods +== Type-safe Query Methods MongoDB repository and its reactive counterpart integrates with the http://www.querydsl.com/[Querydsl] project, which provides a way to perform type-safe queries. @@ -901,7 +341,7 @@ NOTE: Please note that joins (DBRef's) are not supported with Reactive MongoDB s ====== [[mongodb.repositories.queries.full-text]] -=== Full-text Search Queries +== Full-text Search Queries MongoDB's full-text search feature is store-specific and, therefore, can be found on `MongoRepository` rather than on the more general `CrudRepository`. We need a document with a full-text index (see "`xref:mongodb/mapping/mapping.adoc#mapping-usage-indexes.text-index[Text Indexes]`" to learn how to create a full-text index). @@ -944,230 +384,3 @@ criteria = TextCriteria.forDefaultLanguage().matching("film"); Page page = repository.findAllBy(criteria, PageRequest.of(1, 1, sort)); List result = repository.findByTitleOrderByScoreDesc("mongodb", criteria); ---- - - -[[mongodb.repositories.queries.update]] -=== Repository Update Methods - -You can also use the keywords in the preceding table to create queries that identify matching documents for running updates on them. -The actual update action is defined by the `@Update` annotation on the method itself, as the following listing shows. -Note that the naming schema for derived queries starts with `find`. -Using `update` (as in `updateAllByLastname(...)`) is allowed only in combination with `@Query`. - -The update is applied to *all* matching documents and it is *not* possible to limit the scope by passing in a `Page` or by using any of the <>. -The return type can be either `void` or a _numeric_ type, such as `long`, to hold the number of modified documents. - -.Update Methods -==== -[source,java] ----- -public interface PersonRepository extends CrudRepository { - - @Update("{ '$inc' : { 'visits' : 1 } }") - long findAndIncrementVisitsByLastname(String lastname); <1> - - @Update("{ '$inc' : { 'visits' : ?1 } }") - void findAndIncrementVisitsByLastname(String lastname, int increment); <2> - - @Update("{ '$inc' : { 'visits' : ?#{[1]} } }") - long findAndIncrementVisitsUsingSpELByLastname(String lastname, int increment); <3> - - @Update(pipeline = {"{ '$set' : { 'visits' : { '$add' : [ '$visits', ?1 ] } } }"}) - void findAndIncrementVisitsViaPipelineByLastname(String lastname, int increment); <4> - - @Update("{ '$push' : { 'shippingAddresses' : ?1 } }") - long findAndPushShippingAddressByEmail(String email, Address address); <5> - - @Query("{ 'lastname' : ?0 }") - @Update("{ '$inc' : { 'visits' : ?1 } }") - void updateAllByLastname(String lastname, int increment); <6> -} ----- - -<1> The filter query for the update is derived from the method name. -The update is "`as is`" and does not bind any parameters. -<2> The actual increment value is defined by the `increment` method argument that is bound to the `?1` placeholder. -<3> Use the Spring Expression Language (SpEL) for parameter binding. -<4> Use the `pipeline` attribute to issue xref:mongodb/template-crud-operations.adoc#mongo-template.aggregation-update[aggregation pipeline updates]. -<5> The update may contain complex objects. -<6> Combine a xref:mongodb/repositories/repositories.adoc#mongodb.repositories.queries.json-based[string based query] with an update. -==== - -WARNING: Repository updates do not emit persistence nor mapping lifecycle events. - -[[mongodb.repositories.queries.delete]] -=== Repository Delete Queries - -The keywords in the preceding table can be used in conjunction with `delete…By` or `remove…By` to create queries that delete matching documents. - -.`Delete…By` Query -[tabs] -====== -Imperative:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="primary"] ----- -public interface PersonRepository extends MongoRepository { - - List deleteByLastname(String lastname); <1> - - Long deletePersonByLastname(String lastname); <2> - - @Nullable - Person deleteSingleByLastname(String lastname); <3> - - Optional deleteByBirthdate(Date birthdate); <4> -} ----- -<1> Using a return type of `List` retrieves and returns all matching documents before actually deleting them. -<2> A numeric return type directly removes the matching documents, returning the total number of documents removed. -<3> A single domain type result retrieves and removes the first matching document. -<4> Same as in 3 but wrapped in an `Optional` type. - -Reactive:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="secondary"] ----- -public interface PersonRepository extends ReactiveMongoRepository { - - Flux deleteByLastname(String lastname); <1> - - Mono deletePersonByLastname(String lastname); <2> - - Mono deleteSingleByLastname(String lastname); <3> -} ----- -<1> Using a return type of `Flux` retrieves and returns all matching documents before actually deleting them. -<2> A numeric return type directly removes the matching documents, returning the total number of documents removed. -<3> A single domain type result retrieves and removes the first matching document. -====== - -[[mongodb.repositories.queries.aggregation]] -== Aggregation Repository Methods - -The repository layer offers means to interact with xref:mongodb/aggregation-framework.adoc[the aggregation framework] via annotated repository query methods. -Similar to the xref:mongodb/repositories/repositories.adoc#mongodb.repositories.queries.json-based[JSON based queries], you can define a pipeline using the `org.springframework.data.mongodb.repository.Aggregation` annotation. -The definition may contain simple placeholders like `?0` as well as link:{springDocsUrl}/core.html#expressions[SpEL expressions] `?#{ … }`. - -.Aggregating Repository Method -==== -[source,java] ----- -public interface PersonRepository extends CrudRepository { - - @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") - List groupByLastnameAndFirstnames(); <1> - - @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") - List groupByLastnameAndFirstnames(Sort sort); <2> - - @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : ?0 } } }") - List groupByLastnameAnd(String property); <3> - - @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : ?0 } } }") - Slice groupByLastnameAnd(String property, Pageable page); <4> - - @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") - Stream groupByLastnameAndFirstnamesAsStream(); <5> - - @Aggregation("{ $group : { _id : null, total : { $sum : $age } } }") - SumValue sumAgeUsingValueWrapper(); <6> - - @Aggregation("{ $group : { _id : null, total : { $sum : $age } } }") - Long sumAge(); <7> - - @Aggregation("{ $group : { _id : null, total : { $sum : $age } } }") - AggregationResults sumAgeRaw(); <8> - - @Aggregation("{ '$project': { '_id' : '$lastname' } }") - List findAllLastnames(); <9> - - @Aggregation(pipeline = { - "{ $group : { _id : '$author', books: { $push: '$title' } } }", - "{ $out : 'authors' }" - }) - void groupAndOutSkippingOutput(); <10> -} ----- -[source,java] ----- -public class PersonAggregate { - - private @Id String lastname; <2> - private List names; - - public PersonAggregate(String lastname, List names) { - // ... - } - - // Getter / Setter omitted -} - -public class SumValue { - - private final Long total; <6> <8> - - public SumValue(Long total) { - // ... - } - - // Getter omitted -} ----- -<1> Aggregation pipeline to group first names by `lastname` in the `Person` collection returning these as `PersonAggregate`. -<2> If `Sort` argument is present, `$sort` is appended after the declared pipeline stages so that it only affects the order of the final results after having passed all other aggregation stages. -Therefore, the `Sort` properties are mapped against the methods return type `PersonAggregate` which turns `Sort.by("lastname")` into `{ $sort : { '_id', 1 } }` because `PersonAggregate.lastname` is annotated with `@Id`. -<3> Replaces `?0` with the given value for `property` for a dynamic aggregation pipeline. -<4> `$skip`, `$limit` and `$sort` can be passed on via a `Pageable` argument. Same as in <2>, the operators are appended to the pipeline definition. Methods accepting `Pageable` can return `Slice` for easier pagination. -<5> Aggregation methods can return `Stream` to consume results directly from an underlying cursor. Make sure to close the stream after consuming it to release the server-side cursor by either calling `close()` or through `try-with-resources`. -<6> Map the result of an aggregation returning a single `Document` to an instance of a desired `SumValue` target type. -<7> Aggregations resulting in single document holding just an accumulation result like e.g. `$sum` can be extracted directly from the result `Document`. -To gain more control, you might consider `AggregationResult` as method return type as shown in <7>. -<8> Obtain the raw `AggregationResults` mapped to the generic target wrapper type `SumValue` or `org.bson.Document`. -<9> Like in <6>, a single value can be directly obtained from multiple result ``Document``s. -<10> Skips the output of the `$out` stage when return type is `void`. -==== - -In some scenarios, aggregations might require additional options, such as a maximum run time, additional log comments, or the permission to temporarily write data to disk. -Use the `@Meta` annotation to set those options via `maxExecutionTimeMs`, `comment` or `allowDiskUse`. - -[source,java] ----- -interface PersonRepository extends CrudRepository { - - @Meta(allowDiskUse = true) - @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") - List groupByLastnameAndFirstnames(); -} ----- - -Or use `@Meta` to create your own annotation as shown in the sample below. - -[source,java] ----- -@Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.METHOD }) -@Meta(allowDiskUse = true) -@interface AllowDiskUse { } - -interface PersonRepository extends CrudRepository { - - @AllowDiskUse - @Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }") - List groupByLastnameAndFirstnames(); -} ----- - -[NOTE] -==== -Simple-type single-result inspects the returned `Document` and checks for the following: - -. Only one entry in the document, return it. -. Two entries, one is the `_id` value. Return the other. -. Return for the first value assignable to the return type. -. Throw an exception if none of the above is applicable. -==== - -WARNING: The `Page` return type is not supported for repository methods using `@Aggregation`. However, you can use a -`Pageable` argument to add `$skip`, `$limit` and `$sort` to the pipeline and let the method return `Slice`. - diff --git a/src/main/antora/modules/ROOT/pages/mongodb/template-collection-management.adoc b/src/main/antora/modules/ROOT/pages/mongodb/template-collection-management.adoc index 4e78dc607..00b3f8216 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/template-collection-management.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb/template-collection-management.adoc @@ -82,7 +82,7 @@ template.indexOps(Venue.class) .ensureIndex(new GeospatialIndex("location")); ---- -NOTE: `Index` and `GeospatialIndex` support configuration of xref:mongodb/template-query-options.adoc#mongo.query.collation[collations]. +NOTE: `Index` and `GeospatialIndex` support configuration of xref:mongodb/template-query-operations.adoc#mongo.query.collation[collations]. [[mongo-template.index-and-collections.access]] == Accessing Index Information diff --git a/src/main/antora/modules/ROOT/pages/mongodb/template-config.adoc b/src/main/antora/modules/ROOT/pages/mongodb/template-config.adoc index 25739a8fb..ac0189454 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/template-config.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb/template-config.adoc @@ -1,5 +1,5 @@ [[mongo-template.instantiating]] -= MongoTemplate Configuration += Configuration You can use the following configuration to create and register an instance of `MongoTemplate`, as the following example shows: @@ -68,7 +68,7 @@ Other optional properties that you might like to set when creating a `MongoTempl [[mongo-template.read-preference]] == Default Read Preference -The default read preference applied to read operations if no other preference was defined via the xref:mongodb/template-query-options.adoc#mongo.query.read-preference[Query]. +The default read preference applied to read operations if no other preference was defined via the xref:mongodb/template-query-operations.adoc#mongo.query.read-preference[Query]. [[mongo-template.writeresultchecking]] == WriteResultChecking Policy @@ -115,7 +115,7 @@ public class MyAppWriteConcernResolver implements WriteConcernResolver { [[mongo-template.entity-lifecycle-events]] == Publish entity lifecycle events -The template publishes xref:mongodb/mapping/lifecycle-events.adoc#mongodb.mapping-usage.events[lifecycle events]. +The template publishes xref:mongodb/lifecycle-events.adoc#mongodb.mapping-usage.events[lifecycle events]. In case there are no listeners present, this feature can be disabled. [source,java] @@ -131,7 +131,7 @@ MongoOperations mongoTemplate(MongoClient mongoClient) { [[mongo-template.entity-callbacks-config]] == Configure EntityCallbacks -Nest to lifecycle events the template invokes xref:mongodb/mapping/entity-callbacks.adoc[EntityCallbacks] which can be (if not auto configured) set via the template API. +Nest to lifecycle events the template invokes xref:mongodb/lifecycle-events.adoc#mongo.entity-callbacks[EntityCallbacks] which can be (if not auto configured) set via the template API. [tabs] ====== diff --git a/src/main/antora/modules/ROOT/pages/mongodb/template-crud-operations.adoc b/src/main/antora/modules/ROOT/pages/mongodb/template-crud-operations.adoc index 5366c17ea..c9d26289f 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/template-crud-operations.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb/template-crud-operations.adoc @@ -9,7 +9,7 @@ Consider the following class: [source,java] ---- -include::example$Person.java[tags=class] +include::example$example/Person.java[tags=class] ---- Given the `Person` class in the preceding example, you can save, update and delete the object, as the following example shows: @@ -112,7 +112,7 @@ public class ReactiveMongoApplication { The preceding example is meant to show the use of save, update, and remove operations on `MongoTemplate` / `ReactiveMongoTemplate` and not to show complex mapping functionality. The query syntax used in the preceding example is explained in more detail in the section "`xref:mongodb/template-query-operations.adoc[Querying Documents]`". -IMPORTANT: MongoDB requires that you have an `_id` field for all documents. Please refer to the xref:mongodb/template-id-handling.adoc[id handling] section for details on the special treatment of this field. +IMPORTANT: MongoDB requires that you have an `_id` field for all documents. Please refer to the xref:mongodb/template-crud-operations.adoc[ID handling] section for details on the special treatment of this field. IMPORTANT: MongoDB collections can contain documents that represent instances of a variety of types. Please refer to the xref:mongodb/converters-type-mapping.adoc[type mapping] for details. @@ -178,6 +178,50 @@ A similar set of insert operations is also available: * `void` *insert* `(Object objectToSave)`: Insert the object to the default collection. * `void` *insert* `(Object objectToSave, String collectionName)`: Insert the object to the specified collection. +[[mongo-template.id-handling]] +=== How the `_id` Field is Handled in the Mapping Layer + +MongoDB requires that you have an `_id` field for all documents. +If you do not provide one, the driver assigns an `ObjectId` with a generated value. When you use the `MappingMongoConverter`, certain rules govern how properties from the Java class are mapped to this `_id` field: + +. A property or field annotated with `@Id` (`org.springframework.data.annotation.Id`) maps to the `_id` field. +. A property or field without an annotation but named `id` maps to the `_id` field. + +The following outlines what type conversion, if any, is done on the property mapped to the `_id` document field when using the `MappingMongoConverter` (the default for `MongoTemplate`). + +. If possible, an `id` property or field declared as a `String` in the Java class is converted to and stored as an `ObjectId` by using a Spring `Converter`. Valid conversion rules are delegated to the MongoDB Java driver. If it cannot be converted to an `ObjectId`, then the value is stored as a string in the database. +. An `id` property or field declared as `BigInteger` in the Java class is converted to and stored as an `ObjectId` by using a Spring `Converter`. + +If no field or property specified in the previous sets of rules is present in the Java class, an implicit `_id` file is generated by the driver but not mapped to a property or field of the Java class. + +When querying and updating, `MongoTemplate` uses the converter that corresponds to the preceding rules for saving documents so that field names and types used in your queries can match what is in your domain classes. + +Some environments require a customized approach to map `Id` values such as data stored in MongoDB that did not run through the Spring Data mapping layer. Documents can contain `_id` values that can be represented either as `ObjectId` or as `String`. +Reading documents from the store back to the domain type works just fine. Querying for documents via their `id` can be cumbersome due to the implicit `ObjectId` conversion. Therefore documents cannot be retrieved that way. +For those cases `@MongoId` provides more control over the actual id mapping attempts. + +.`@MongoId` mapping +==== +[source,java] +---- +public class PlainStringId { + @MongoId String id; <1> +} + +public class PlainObjectId { + @MongoId ObjectId id; <2> +} + +public class StringToObjectId { + @MongoId(FieldType.OBJECT_ID) String id; <3> +} +---- +<1> The id is treated as `String` without further conversion. +<2> The id is treated as `ObjectId`. +<3> The id is treated as `ObjectId` if the given `String` is a valid `ObjectId` hex, otherwise as `String`. Corresponds to `@Id` usage. +==== + + [[mongo-template.save-insert.collection]] === Into Which Collection Are My Documents Saved? @@ -246,7 +290,7 @@ Mono result = template.bulkOps(BulkMode.ORDERED, Person.class) [NOTE] ==== Server performance of batch and bulk is identical. -However bulk operations do not publish xref:mongodb/mapping/lifecycle-events.adoc[lifecycle events]. +However bulk operations do not publish xref:mongodb/lifecycle-events.adoc[lifecycle events]. ==== [[mongodb-template-update]] diff --git a/src/main/antora/modules/ROOT/pages/mongodb/template-id-handling.adoc b/src/main/antora/modules/ROOT/pages/mongodb/template-id-handling.adoc deleted file mode 100644 index 966a23784..000000000 --- a/src/main/antora/modules/ROOT/pages/mongodb/template-id-handling.adoc +++ /dev/null @@ -1,42 +0,0 @@ -[[mongo-template.id-handling]] -== How the `_id` Field is Handled in the Mapping Layer - -MongoDB requires that you have an `_id` field for all documents. -If you do not provide one, the driver assigns an `ObjectId` with a generated value. When you use the `MappingMongoConverter`, certain rules govern how properties from the Java class are mapped to this `_id` field: - -. A property or field annotated with `@Id` (`org.springframework.data.annotation.Id`) maps to the `_id` field. -. A property or field without an annotation but named `id` maps to the `_id` field. - -The following outlines what type conversion, if any, is done on the property mapped to the `_id` document field when using the `MappingMongoConverter` (the default for `MongoTemplate`). - -. If possible, an `id` property or field declared as a `String` in the Java class is converted to and stored as an `ObjectId` by using a Spring `Converter`. Valid conversion rules are delegated to the MongoDB Java driver. If it cannot be converted to an `ObjectId`, then the value is stored as a string in the database. -. An `id` property or field declared as `BigInteger` in the Java class is converted to and stored as an `ObjectId` by using a Spring `Converter`. - -If no field or property specified in the previous sets of rules is present in the Java class, an implicit `_id` file is generated by the driver but not mapped to a property or field of the Java class. - -When querying and updating, `MongoTemplate` uses the converter that corresponds to the preceding rules for saving documents so that field names and types used in your queries can match what is in your domain classes. - -Some environments require a customized approach to map `Id` values such as data stored in MongoDB that did not run through the Spring Data mapping layer. Documents can contain `_id` values that can be represented either as `ObjectId` or as `String`. -Reading documents from the store back to the domain type works just fine. Querying for documents via their `id` can be cumbersome due to the implicit `ObjectId` conversion. Therefore documents cannot be retrieved that way. -For those cases `@MongoId` provides more control over the actual id mapping attempts. - -.`@MongoId` mapping -==== -[source,java] ----- -public class PlainStringId { - @MongoId String id; <1> -} - -public class PlainObjectId { - @MongoId ObjectId id; <2> -} - -public class StringToObjectId { - @MongoId(FieldType.OBJECT_ID) String id; <3> -} ----- -<1> The id is treated as `String` without further conversion. -<2> The id is treated as `ObjectId`. -<3> The id is treated as `ObjectId` if the given `String` is a valid `ObjectId` hex, otherwise as `String`. Corresponds to `@Id` usage. -==== diff --git a/src/main/antora/modules/ROOT/pages/mongodb/template-query-operations.adoc b/src/main/antora/modules/ROOT/pages/mongodb/template-query-operations.adoc index e32c46199..4505e11a9 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/template-query-operations.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb/template-query-operations.adoc @@ -97,7 +97,7 @@ The `Criteria` class provides the following methods, all of which correspond to * `Criteria` *sampleRate* `(double sampleRate)` Creates a criterion using the `$sampleRate` operator * `Criteria` *size* `(int s)` Creates a criterion using the `$size` operator * `Criteria` *type* `(int t)` Creates a criterion using the `$type` operator -* `Criteria` *matchingDocumentStructure* `(MongoJsonSchema schema)` Creates a criterion using the `$jsonSchema` operator for xref:mongodb/template-collection-schema.adoc[JSON schema criteria]. `$jsonSchema` can only be applied on the top level of a query and not property specific. Use the `properties` attribute of the schema to match against nested fields. +* `Criteria` *matchingDocumentStructure* `(MongoJsonSchema schema)` Creates a criterion using the `$jsonSchema` operator for xref:mongodb/mapping/mapping-schema.adoc[JSON schema criteria]. `$jsonSchema` can only be applied on the top level of a query and not property specific. Use the `properties` attribute of the schema to match against nested fields. * `Criteria` *bits()* is the gateway to https://docs.mongodb.com/manual/reference/operator/query-bitwise/[MongoDB bitwise query operators] like `$bitsAllClear`. The Criteria class also provides the following methods for geospatial queries. @@ -200,6 +200,87 @@ query.fields() `@Query(fields="…")` allows usage of expression field projections at `Repository` level as described in xref:mongodb/repositories/repositories.adoc#mongodb.repositories.queries.json-based[MongoDB JSON-based Query Methods and Field Restriction]. +[[mongo.query.additional-query-options]] +== Additional Query Options + +MongoDB offers various ways of applying meta information, like a comment or a batch size, to a query.Using the `Query` API +directly there are several methods for those options. + +[[mongo.query.hints]] +=== Hints + +Index hints can be applied in two ways, using the index name or its field definition. + +==== +[source,java] +---- +template.query(Person.class) + .matching(query("...").withHint("index-to-use")); + +template.query(Person.class) + .matching(query("...").withHint("{ firstname : 1 }")); +---- +==== + +[[mongo.query.cursor-size]] +=== Cursor Batch Size + +The cursor batch size defines the number of documents to return in each response batch. +==== +[source,java] +---- +Query query = query(where("firstname").is("luke")) + .cursorBatchSize(100) +---- +==== + +[[mongo.query.collation]] +=== Collations + +Using collations with collection operations is a matter of specifying a `Collation` instance in your query or operation options, as the following two examples show: + +==== +[source,java] +---- +Collation collation = Collation.of("de"); + +Query query = new Query(Criteria.where("firstName").is("Amél")) + .collation(collation); + +List results = template.find(query, Person.class); +---- +==== + +[[mongo.query.read-preference]] +=== Read Preference + +The `ReadPreference` to use can be set directly on the `Query` object to be run as outlined below. + +==== +[source,java] +---- +template.find(Person.class) + .matching(query(where(...)).withReadPreference(ReadPreference.secondary())) + .all(); +---- +==== + +NOTE: The preference set on the `Query` instance will supersede the default `ReadPreference` of `MongoTemplate`. + +[[mongo.query.comment]] +=== Comments + +Queries can be equipped with comments which makes them easier to look up in server logs. + +==== +[source,java] +---- +template.find(Person.class) + .matching(query(where(...)).comment("Use the force luke!")) + .all(); +---- +==== + [[mongo-template.query.distinct]] == Query Distinct Values @@ -741,7 +822,7 @@ Note that these two optional flags have been introduced in MongoDB 3.2 and are n [[mongo.query-by-example]] == Query by Example -Some general information about Query By Example support in Spring Data can be found in the commons documentation. +xref:repositories/query-by-example.adoc[Query by Example] can be used on the Template API level run example queries. The following snipped shows how to query by example: @@ -858,7 +939,7 @@ template.find(query(matchingDocumentStructure(schema)), Person.class); ---- ==== -Please refer to the xref:mongodb/template-collection-schema.adoc[JSON Schema] section to learn more about the schema support in Spring Data MongoDB. +Please refer to the xref:mongodb/mapping/mapping-schema.adoc[JSON Schema] section to learn more about the schema support in Spring Data MongoDB. diff --git a/src/main/antora/modules/ROOT/pages/mongodb/template-query-options.adoc b/src/main/antora/modules/ROOT/pages/mongodb/template-query-options.adoc deleted file mode 100644 index 02f14f696..000000000 --- a/src/main/antora/modules/ROOT/pages/mongodb/template-query-options.adoc +++ /dev/null @@ -1,81 +0,0 @@ -[[mongo.query.additional-query-options]] -= Additional Query Options - -MongoDB offers various ways of applying meta information, like a comment or a batch size, to a query.Using the `Query` API -directly there are several methods for those options. - -[[mongo.query.hints]] -== Hints - -Index hints can be applied in two ways, using the index name or its field definition. - -==== -[source,java] ----- -template.query(Person.class) - .matching(query("...").withHint("index-to-use")); - -template.query(Person.class) - .matching(query("...").withHint("{ firstname : 1 }")); ----- -==== - -[[mongo.query.cursor-size]] -== Cursor Batch Size - -The cursor batch size defines the number of documents to return in each response batch. -==== -[source,java] ----- -Query query = query(where("firstname").is("luke")) - .cursorBatchSize(100) ----- -==== - -[[mongo.query.collation]] -== Collations - -Using collations with collection operations is a matter of specifying a `Collation` instance in your query or operation options, as the following two examples show: - -==== -[source,java] ----- -Collation collation = Collation.of("de"); - -Query query = new Query(Criteria.where("firstName").is("Amél")) - .collation(collation); - -List results = template.find(query, Person.class); ----- -==== - -[[mongo.query.read-preference]] -== Read Preference - -The `ReadPreference` to use can be set directly on the `Query` object to be run as outlined below. - -==== -[source,java] ----- -template.find(Person.class) - .matching(query(where(...)).withReadPreference(ReadPreference.secondary())) - .all(); ----- -==== - -NOTE: The preference set on the `Query` instance will supersede the default `ReadPreference` of `MongoTemplate`. - -[[mongo.query.comment]] -== Comments - -Queries can be equipped with comments which makes them easier to look up in server logs. - -==== -[source,java] ----- -template.find(Person.class) - .matching(query(where(...)).comment("Use the force luke!")) - .all(); ----- -==== - diff --git a/src/main/antora/modules/ROOT/pages/repositories/core-concepts.adoc b/src/main/antora/modules/ROOT/pages/repositories/core-concepts.adoc index 6e7938f21..1a4af7a60 100644 --- a/src/main/antora/modules/ROOT/pages/repositories/core-concepts.adoc +++ b/src/main/antora/modules/ROOT/pages/repositories/core-concepts.adoc @@ -1,6 +1,6 @@ include::{commons}@data-commons::page$repositories/core-concepts.adoc[] -[[cassandra.entity-persistence.state-detection-strategies]] +[[mongodb.entity-persistence.state-detection-strategies]] include::{commons}@data-commons::page$is-new-state-detection.adoc[leveloffset=+1] [NOTE] diff --git a/src/main/antora/modules/ROOT/pages/repositories/projections.adoc b/src/main/antora/modules/ROOT/pages/repositories/projections.adoc index 875f61abe..9302203c5 100644 --- a/src/main/antora/modules/ROOT/pages/repositories/projections.adoc +++ b/src/main/antora/modules/ROOT/pages/repositories/projections.adoc @@ -1,4 +1,2 @@ -[[cassandra.projections]] -= Projections - -include::{commons}@data-commons::page$repositories/projections.adoc[leveloffset=+1] +[[mongodb.projections]] +include::{commons}@data-commons::page$repositories/projections.adoc[] diff --git a/src/main/antora/modules/ROOT/pages/mongodb/query-by-example.adoc b/src/main/antora/modules/ROOT/pages/repositories/query-by-example.adoc similarity index 86% rename from src/main/antora/modules/ROOT/pages/mongodb/query-by-example.adoc rename to src/main/antora/modules/ROOT/pages/repositories/query-by-example.adoc index 93929bf91..6c07119c7 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/query-by-example.adoc +++ b/src/main/antora/modules/ROOT/pages/repositories/query-by-example.adoc @@ -1,7 +1,7 @@ -[[query-by-example.running]] -= Running an Example +include::{commons}@data-commons::query-by-example.adoc[] -TODO: move this section to the repositories documentation +[[query-by-example.running]] +== Running an Example The following example shows how to query by example when using a repository (of `Person` objects, in this case): diff --git a/src/main/asciidoc/images/epub-cover.png b/src/main/asciidoc/images/epub-cover.png deleted file mode 100644 index 7be1d08b3e38461536357ea31bde85587cbd0c2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66019 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

f$GBB>ixy9dlh?v&LNRiLF!Pt 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 - - - - Spring Data MongoDB - Reference Guide - Mark Pollack, Thomas Risberg, - Oliver Gierke, Costin Leau, - Jon Brisbin, Thomas Darimont, - Christoph Strobl, Mark Paluch, - Jay Bryant - diff --git a/src/main/asciidoc/images/jconsole.png b/src/main/asciidoc/images/jconsole.png deleted file mode 100644 index 267aee8a4b41323e3d3e0658af3267545897866c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49294 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 C1l}_M