5 changed files with 266 additions and 205 deletions
@ -1,56 +0,0 @@
@@ -1,56 +0,0 @@
|
||||
[[mongo.query.fluent-template-api]] |
||||
= Fluent Template API |
||||
|
||||
The `MongoOperations` interface is one of the central components when it comes to more low-level interaction with MongoDB. It offers a wide range of methods covering needs from collection creation, index creation, and CRUD operations to more advanced functionality, such as Map-Reduce and aggregations. |
||||
You can find multiple overloads for each method. Most of them cover optional or nullable parts of the API. |
||||
|
||||
`FluentMongoOperations` provides a more narrow interface for the common methods of `MongoOperations` and provides a more readable, fluent API. |
||||
The entry points (`insert(…)`, `find(…)`, `update(…)`, and others) follow a natural naming schema based on the operation to be run. Moving on from the entry point, the API is designed to offer only context-dependent methods that lead to a terminating method that invokes the actual `MongoOperations` counterpart -- the `all` method in the case of the following example: |
||||
|
||||
==== |
||||
[source,java] |
||||
---- |
||||
List<SWCharacter> all = ops.find(SWCharacter.class) |
||||
.inCollection("star-wars") <1> |
||||
.all(); |
||||
---- |
||||
<1> Skip this step if `SWCharacter` defines the collection with `@Document` or if you use the class name as the collection name, which is fine. |
||||
==== |
||||
|
||||
Sometimes, a collection in MongoDB holds entities of different types, such as a `Jedi` within a collection of `SWCharacters`. |
||||
To use different types for `Query` and return value mapping, you can use `as(Class<?> targetType)` to map results differently, as the following example shows: |
||||
|
||||
==== |
||||
[source,java] |
||||
---- |
||||
List<Jedi> all = ops.find(SWCharacter.class) <1> |
||||
.as(Jedi.class) <2> |
||||
.matching(query(where("jedi").is(true))) |
||||
.all(); |
||||
---- |
||||
<1> The query fields are mapped against the `SWCharacter` type. |
||||
<2> Resulting documents are mapped into `Jedi`. |
||||
==== |
||||
|
||||
TIP: You can directly apply <<projections>> to result documents by providing the target type via `as(Class<?>)`. |
||||
|
||||
NOTE: Using projections allows `MongoTemplate` to optimize result mapping by limiting the actual response to fields required |
||||
by the projection target type. This applies as long as the `Query` itself does not contain any field restriction and the |
||||
target type is a closed interface or DTO projection. |
||||
|
||||
WARNING: Projections must not be applied to xref:reference/document-references.adoc[DBRefs]. |
||||
|
||||
You can switch between retrieving a single entity and retrieving multiple entities as a `List` or a `Stream` through the terminating methods: `first()`, `one()`, `all()`, or `stream()`. |
||||
|
||||
When writing a geo-spatial query with `near(NearQuery)`, the number of terminating methods is altered to include only the methods that are valid for running a `geoNear` command in MongoDB (fetching entities as a `GeoResult` within `GeoResults`), as the following example shows: |
||||
|
||||
==== |
||||
[source,java] |
||||
---- |
||||
GeoResults<Jedi> results = mongoOps.query(SWCharacter.class) |
||||
.as(Jedi.class) |
||||
.near(alderaan) // NearQuery.near(-73.9667, 40.78).maxDis… |
||||
.all(); |
||||
---- |
||||
==== |
||||
|
||||
@ -1,144 +0,0 @@
@@ -1,144 +0,0 @@
|
||||
[[mongodb-template-query]] |
||||
= Querying Documents in a Collection |
||||
|
||||
Earlier, we saw how to retrieve a single document by using the `findOne` and `findById` methods on `MongoTemplate`. These methods return a single domain object. We can also query for a collection of documents to be returned as a list of domain objects. Assuming that we have a number of `Person` objects with name and age stored as documents in a collection and that each person has an embedded account document with a balance, we can now run a query using the following code: |
||||
|
||||
.Querying for documents using the MongoTemplate |
||||
==== |
||||
[source,java] |
||||
---- |
||||
import static org.springframework.data.mongodb.core.query.Criteria.where; |
||||
import static org.springframework.data.mongodb.core.query.Query.query; |
||||
|
||||
// ... |
||||
|
||||
List<Person> result = template.query(Person.class) |
||||
.matching(query(where("age").lt(50).and("accounts.balance").gt(1000.00d))) |
||||
.all(); |
||||
---- |
||||
==== |
||||
|
||||
All find methods take a `Query` object as a parameter. This object defines the criteria and options used to perform the query. The criteria are specified by using a `Criteria` object that has a static factory method named `where` to instantiate a new `Criteria` object. We recommend using static imports for `org.springframework.data.mongodb.core.query.Criteria.where` and `Query.query` to make the query more readable. |
||||
|
||||
The query should return a list of `Person` objects that meet the specified criteria. The rest of this section lists the methods of the `Criteria` and `Query` classes that correspond to the operators provided in MongoDB. Most methods return the `Criteria` object, to provide a fluent style for the API. |
||||
|
||||
[[mongodb-template-query.criteria]] |
||||
== Methods for the Criteria Class |
||||
|
||||
The `Criteria` class provides the following methods, all of which correspond to operators in MongoDB: |
||||
|
||||
* `Criteria` *all* `(Object o)` Creates a criterion using the `$all` operator |
||||
* `Criteria` *and* `(String key)` Adds a chained `Criteria` with the specified `key` to the current `Criteria` and returns the newly created one |
||||
* `Criteria` *andOperator* `(Criteria... criteria)` Creates an and query using the `$and` operator for all of the provided criteria (requires MongoDB 2.0 or later) |
||||
* `Criteria` *andOperator* `(Collection<Criteria> criteria)` Creates an and query using the `$and` operator for all of the provided criteria (requires MongoDB 2.0 or later) |
||||
* `Criteria` *elemMatch* `(Criteria c)` Creates a criterion using the `$elemMatch` operator |
||||
* `Criteria` *exists* `(boolean b)` Creates a criterion using the `$exists` operator |
||||
* `Criteria` *gt* `(Object o)` Creates a criterion using the `$gt` operator |
||||
* `Criteria` *gte* `(Object o)` Creates a criterion using the `$gte` operator |
||||
* `Criteria` *in* `(Object... o)` Creates a criterion using the `$in` operator for a varargs argument. |
||||
* `Criteria` *in* `(Collection<?> collection)` Creates a criterion using the `$in` operator using a collection |
||||
* `Criteria` *is* `(Object o)` Creates a criterion using field matching (`{ key:value }`). If the specified value is a document, the order of the fields and exact equality in the document matters. |
||||
* `Criteria` *lt* `(Object o)` Creates a criterion using the `$lt` operator |
||||
* `Criteria` *lte* `(Object o)` Creates a criterion using the `$lte` operator |
||||
* `Criteria` *mod* `(Number value, Number remainder)` Creates a criterion using the `$mod` operator |
||||
* `Criteria` *ne* `(Object o)` Creates a criterion using the `$ne` operator |
||||
* `Criteria` *nin* `(Object... o)` Creates a criterion using the `$nin` operator |
||||
* `Criteria` *norOperator* `(Criteria... criteria)` Creates an nor query using the `$nor` operator for all of the provided criteria |
||||
* `Criteria` *norOperator* `(Collection<Criteria> criteria)` Creates an nor query using the `$nor` operator for all of the provided criteria |
||||
* `Criteria` *not* `()` Creates a criterion using the `$not` meta operator which affects the clause directly following |
||||
* `Criteria` *orOperator* `(Criteria... criteria)` Creates an or query using the `$or` operator for all of the provided criteria |
||||
* `Criteria` *orOperator* `(Collection<Criteria> criteria)` Creates an or query using the `$or` operator for all of the provided criteria |
||||
* `Criteria` *regex* `(String re)` Creates a criterion using a `$regex` |
||||
* `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:reference/mongo-json-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 (see the xref:reference/mongodb/mongo-query/geospatial.adoc[GeoSpatial Queries] section to see them in action): |
||||
|
||||
* `Criteria` *within* `(Circle circle)` Creates a geospatial criterion using `$geoWithin $center` operators. |
||||
* `Criteria` *within* `(Box box)` Creates a geospatial criterion using a `$geoWithin $box` operation. |
||||
* `Criteria` *withinSphere* `(Circle circle)` Creates a geospatial criterion using `$geoWithin $center` operators. |
||||
* `Criteria` *near* `(Point point)` Creates a geospatial criterion using a `$near` operation |
||||
* `Criteria` *nearSphere* `(Point point)` Creates a geospatial criterion using `$nearSphere$center` operations. This is only available for MongoDB 1.7 and higher. |
||||
* `Criteria` *minDistance* `(double minDistance)` Creates a geospatial criterion using the `$minDistance` operation, for use with $near. |
||||
* `Criteria` *maxDistance* `(double maxDistance)` Creates a geospatial criterion using the `$maxDistance` operation, for use with $near. |
||||
|
||||
|
||||
[[mongodb-template-query.query]] |
||||
== Methods for the Query class |
||||
|
||||
The `Query` class has some additional methods that provide options for the query: |
||||
|
||||
* `Query` *addCriteria* `(Criteria criteria)` used to add additional criteria to the query |
||||
* `Field` *fields* `()` used to define fields to be included in the query results |
||||
* `Query` *limit* `(int limit)` used to limit the size of the returned results to the provided limit (used for paging) |
||||
* `Query` *skip* `(int skip)` used to skip the provided number of documents in the results (used for paging) |
||||
* `Query` *with* `(Sort sort)` used to provide sort definition for the results |
||||
* `Query` *with* `(ScrollPosition position)` used to provide a scroll position (Offset- or Keyset-based pagination) to start or resume a `Scroll` |
||||
|
||||
[[mongo-template.querying.field-selection]] |
||||
== Selecting fields |
||||
|
||||
MongoDB supports https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/[projecting fields] returned by a query. |
||||
A projection can include and exclude fields (the `_id` field is always included unless explicitly excluded) based on their name. |
||||
|
||||
.Selecting result fields |
||||
==== |
||||
[source,java] |
||||
---- |
||||
public class Person { |
||||
|
||||
@Id String id; |
||||
String firstname; |
||||
|
||||
@Field("last_name") |
||||
String lastname; |
||||
|
||||
Address address; |
||||
} |
||||
|
||||
query.fields().include("lastname"); <1> |
||||
|
||||
query.fields().exclude("id").include("lastname") <2> |
||||
|
||||
query.fields().include("address") <3> |
||||
|
||||
query.fields().include("address.city") <4> |
||||
|
||||
|
||||
---- |
||||
<1> Result will contain both `_id` and `last_name` via `{ "last_name" : 1 }`. |
||||
<2> Result will only contain the `last_name` via `{ "_id" : 0, "last_name" : 1 }`. |
||||
<3> Result will contain the `_id` and entire `address` object via `{ "address" : 1 }`. |
||||
<4> Result will contain the `_id` and and `address` object that only contains the `city` field via `{ "address.city" : 1 }`. |
||||
==== |
||||
|
||||
Starting with MongoDB 4.4 you can use aggregation expressions for field projections as shown below: |
||||
|
||||
.Computing result fields using expressions |
||||
==== |
||||
[source,java] |
||||
---- |
||||
query.fields() |
||||
.project(MongoExpression.create("'$toUpper' : '$last_name'")) <1> |
||||
.as("last_name"); <2> |
||||
|
||||
query.fields() |
||||
.project(StringOperators.valueOf("lastname").toUpper()) <3> |
||||
.as("last_name"); |
||||
|
||||
query.fields() |
||||
.project(AggregationSpELExpression.expressionOf("toUpper(lastname)")) <4> |
||||
.as("last_name"); |
||||
---- |
||||
<1> Use a native expression. The used field name must refer to field names within the database document. |
||||
<2> Assign the field name to which the expression result is projected. The resulting field name is not mapped against the domain model. |
||||
<3> Use an `AggregationExpression`. Other than native `MongoExpression`, field names are mapped to the ones used in the domain model. |
||||
<4> Use SpEL along with an `AggregationExpression` to invoke expression functions. Field names are mapped to the ones used in the domain model. |
||||
==== |
||||
|
||||
`@Query(fields="…")` allows usage of expression field projections at `Repository` level as described in xref:reference/mongo-repositories.adoc#mongodb.repositories.queries.json-based[MongoDB JSON-based Query Methods and Field Restriction]. |
||||
|
||||
Loading…
Reference in new issue