Querying Documents
You can use the Query
and Criteria
classes to express your queries. They have method names that mirror the native MongoDB operator names, such as lt
, lte
, is
, and others. The Query
and Criteria
classes follow a fluent API style so that you can chain together multiple method criteria and queries while having easy-to-understand code. To improve readability, static imports let you avoid using the 'new' keyword for creating Query
and Criteria
instances. You can also use BasicQuery
to create Query
instances from plain JSON Strings, as shown in the following example:
BasicQuery query = new BasicQuery("{ age : { $lt : 50 }, accounts.balance : { $gt : 1000.00 }}");
List<Person> result = mongoTemplate.find(query, Person.class);
Spring MongoDB also supports GeoSpatial queries (see the GeoSpatial Queries section) and Map-Reduce operations (see the Map-Reduce section.).
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:
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;
…
List<Person> result = mongoTemplate.find(query(where("age").lt(50)
.and("accounts.balance").gt(1000.00d)), Person.class);
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.
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 chainedCriteria
with the specifiedkey
to the currentCriteria
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
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
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
regex(String re)
Creates a criterion using a$regex
-
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 JSON schema criteria.$jsonSchema
can only be applied on the top level of a query and not property specific. Use theproperties
attribute of the schema to match against nested fields. -
Criteria
bits() is the gateway to MongoDB bitwise query operators like$bitsAllClear
.
The Criteria class also provides the following methods for geospatial queries (see the 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.
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
Methods for Querying for Documents
The query methods need to specify the target type T
that is returned, and they are overloaded with an explicit collection name for queries that should operate on a collection other than the one indicated by the return type. The following query methods let you find one or more documents:
-
findAll: Query for a list of objects of type
T
from the collection. -
findOne: Map the results of an ad-hoc query on the collection to a single instance of an object of the specified type.
-
findById: Return an object of the given ID and target class.
-
find: Map the results of an ad-hoc query on the collection to a
List
of the specified type. -
findAndRemove: Map the results of an ad-hoc query on the collection to a single instance of an object of the specified type. The first document that matches the query is returned and removed from the collection in the database.
Query Distinct Values
MongoDB provides an operation to obtain distinct values for a single field by using a query from the resulting documents. Resulting values are not required to have the same data type, nor is the feature limited to simple types. For retrieval, the actual result type does matter for the sake of conversion and typing. The following example shows how to query for distinct values:
template.query(Person.class) (1)
.distinct("lastname") (2)
.all(); (3)
1 | Query the Person collection. |
2 | Select distinct values of the lastname field. The field name is mapped according to the domain types property declaration, taking potential @Field annotations into account. |
3 | Retrieve all distinct values as a List of Object (due to no explicit result type being specified). |
Retrieving distinct values into a Collection
of Object
is the most flexible way, as it tries to determine the property value of the domain type and convert results to the desired type or mapping Document
structures.
Sometimes, when all values of the desired field are fixed to a certain type, it is more convenient to directly obtain a correctly typed Collection
, as shown in the following example:
template.query(Person.class) (1)
.distinct("lastname") (2)
.as(String.class) (3)
.all(); (4)
1 | Query the collection of Person . |
2 | Select distinct values of the lastname field. The fieldname is mapped according to the domain types property declaration, taking potential @Field annotations into account. |
3 | Retrieved values are converted into the desired target type — in this case, String . It is also possible to map the values to a more complex type if the stored field contains a document. |
4 | Retrieve all distinct values as a List of String . If the type cannot be converted into the desired target type, this method throws a DataAccessException . |
GeoSpatial Queries
MongoDB supports GeoSpatial queries through the use of operators such as $near
, $within
, geoWithin
, and $nearSphere
. Methods specific to geospatial queries are available on the Criteria
class. There are also a few shape classes (Box
, Circle
, and Point
) that are used in conjunction with geospatial related Criteria
methods.
Using GeoSpatial queries requires attention when used within MongoDB transactions, see mongo.transactions.behavior. |
To understand how to perform GeoSpatial queries, consider the following Venue
class (taken from the integration tests and relying on the rich MappingMongoConverter
):
@Document(collection="newyork")
public class Venue {
@Id
private String id;
private String name;
private double[] location;
@PersistenceConstructor
Venue(String name, double[] location) {
super();
this.name = name;
this.location = location;
}
public Venue(String name, double x, double y) {
super();
this.name = name;
this.location = new double[] { x, y };
}
public String getName() {
return name;
}
public double[] getLocation() {
return location;
}
@Override
public String toString() {
return "Venue [id=" + id + ", name=" + name + ", location="
+ Arrays.toString(location) + "]";
}
}
To find locations within a Circle
, you can use the following query:
Circle circle = new Circle(-73.99171, 40.738868, 0.01);
List<Venue> venues =
template.find(new Query(Criteria.where("location").within(circle)), Venue.class);
To find venues within a Circle
using spherical coordinates, you can use the following query:
Circle circle = new Circle(-73.99171, 40.738868, 0.003712240453784);
List<Venue> venues =
template.find(new Query(Criteria.where("location").withinSphere(circle)), Venue.class);
To find venues within a Box
, you can use the following query:
//lower-left then upper-right
Box box = new Box(new Point(-73.99756, 40.73083), new Point(-73.988135, 40.741404));
List<Venue> venues =
template.find(new Query(Criteria.where("location").within(box)), Venue.class);
To find venues near a Point
, you can use the following queries:
Point point = new Point(-73.99171, 40.738868);
List<Venue> venues =
template.find(new Query(Criteria.where("location").near(point).maxDistance(0.01)), Venue.class);
Point point = new Point(-73.99171, 40.738868);
List<Venue> venues =
template.find(new Query(Criteria.where("location").near(point).minDistance(0.01).maxDistance(100)), Venue.class);
To find venues near a Point
using spherical coordinates, you can use the following query:
Point point = new Point(-73.99171, 40.738868);
List<Venue> venues =
template.find(new Query(
Criteria.where("location").nearSphere(point).maxDistance(0.003712240453784)),
Venue.class);
Geo-near Queries
MongoDB supports querying the database for geo locations and calculating the distance from a given origin at the same time. With geo-near queries, you can express queries such as "find all restaurants in the surrounding 10 miles". To let you do so, MongoOperations
provides geoNear(…)
methods that take a NearQuery
as an argument (as well as the already familiar entity type and collection), as shown in the following example:
Point location = new Point(-73.99171, 40.738868);
NearQuery query = NearQuery.near(location).maxDistance(new Distance(10, Metrics.MILES));
GeoResults<Restaurant> = operations.geoNear(query, Restaurant.class);
We use the NearQuery
builder API to set up a query to return all Restaurant
instances surrounding the given Point
out to 10 miles. The Metrics
enum used here actually implements an interface so that other metrics could be plugged into a distance as well. A Metric
is backed by a multiplier to transform the distance value of the given metric into native distances. The sample shown here would consider the 10 to be miles. Using one of the built-in metrics (miles and kilometers) automatically triggers the spherical flag to be set on the query. If you want to avoid that, pass plain double
values into maxDistance(…)
. For more information, see the JavaDoc of NearQuery
and Distance
.
The geo-near operations return a GeoResults
wrapper object that encapsulates GeoResult
instances. Wrapping GeoResults
allows accessing the average distance of all results. A single GeoResult
object carries the entity found plus its distance from the origin.
GeoJSON Support
MongoDB supports GeoJSON and simple (legacy) coordinate pairs for geospatial data. Those formats can both be used for storing as well as querying data. See the MongoDB manual on GeoJSON support to learn about requirements and restrictions.
GeoJSON Types in Domain Classes
Usage of GeoJSON types in domain classes is straightforward. The org.springframework.data.mongodb.core.geo
package contains types such as GeoJsonPoint
, GeoJsonPolygon
, and others. These types are extend the existing org.springframework.data.geo
types. The following example uses a GeoJsonPoint
:
public class Store {
String id;
/**
* location is stored in GeoJSON format.
* {
* "type" : "Point",
* "coordinates" : [ x, y ]
* }
*/
GeoJsonPoint location;
}
GeoJSON Types in Repository Query Methods
Using GeoJSON types as repository query parameters forces usage of the $geometry
operator when creating the query, as the following example shows:
public interface StoreRepository extends CrudRepository<Store, String> {
List<Store> findByLocationWithin(Polygon polygon); (1)
}
/*
* {
* "location": {
* "$geoWithin": {
* "$geometry": {
* "type": "Polygon",
* "coordinates": [
* [
* [-73.992514,40.758934],
* [-73.961138,40.760348],
* [-73.991658,40.730006],
* [-73.992514,40.758934]
* ]
* ]
* }
* }
* }
* }
*/
repo.findByLocationWithin( (2)
new GeoJsonPolygon(
new Point(-73.992514, 40.758934),
new Point(-73.961138, 40.760348),
new Point(-73.991658, 40.730006),
new Point(-73.992514, 40.758934))); (3)
/*
* {
* "location" : {
* "$geoWithin" : {
* "$polygon" : [ [-73.992514,40.758934] , [-73.961138,40.760348] , [-73.991658,40.730006] ]
* }
* }
* }
*/
repo.findByLocationWithin( (4)
new Polygon(
new Point(-73.992514, 40.758934),
new Point(-73.961138, 40.760348),
new Point(-73.991658, 40.730006));
1 | Repository method definition using the commons type allows calling it with both the GeoJSON and the legacy format. |
2 | Use GeoJSON type to make use of $geometry operator. |
3 | Note that GeoJSON polygons need to define a closed ring. |
4 | Use the legacy format $polygon operator. |
Full-text Queries
Since version 2.6 of MongoDB, you can run full-text queries by using the $text
operator. Methods and operations specific to full-text queries are available in TextQuery
and TextCriteria
. When doing full text search, see the MongoDB reference for its behavior and limitations.
Full-text Search
Before you can actually use full-text search, you must set up the search index correctly. See Text Index for more detail on how to create index structures. The following example shows how to set up a full-text search:
db.foo.createIndex(
{
title : "text",
content : "text"
},
{
weights : {
title : 3
}
}
)
A query searching for coffee cake
, sorted by relevance according to the weights
, can be defined and executed as follows:
Query query = TextQuery.searching(new TextCriteria().matchingAny("coffee", "cake")).sortByScore();
List<Document> page = template.find(query, Document.class);
You can exclude search terms by prefixing the term with -
or by using notMatching
, as shown in the following example (note that the two lines have the same effect and are thus redundant):
// search for 'coffee' and not 'cake'
TextQuery.searching(new TextCriteria().matching("coffee").matching("-cake"));
TextQuery.searching(new TextCriteria().matching("coffee").notMatching("cake"));
TextCriteria.matching
takes the provided term as is. Therefore, you can define phrases by putting them between double quotation marks (for example, \"coffee cake\")
or using by TextCriteria.phrase.
The following example shows both ways of defining a phrase:
// search for phrase 'coffee cake'
TextQuery.searching(new TextCriteria().matching("\"coffee cake\""));
TextQuery.searching(new TextCriteria().phrase("coffee cake"));
You can set flags for $caseSensitive
and $diacriticSensitive
by using the corresponding methods on TextCriteria
. Note that these two optional flags have been introduced in MongoDB 3.2 and are not included in the query unless explicitly set.
Collations
Since version 3.4, MongoDB supports collations for collection and index creation and various query operations. Collations define string comparison rules based on the ICU collations. A collation document consists of various properties that are encapsulated in Collation
, as the following listing shows:
Collation collation = Collation.of("fr") (1)
.strength(ComparisonLevel.secondary() (2)
.includeCase())
.numericOrderingEnabled() (3)
.alternate(Alternate.shifted().punct()) (4)
.forwardDiacriticSort() (5)
.normalizationEnabled(); (6)
1 | Collation requires a locale for creation. This can be either a string representation of the locale, a Locale (considering language, country, and variant) or a CollationLocale . The locale is mandatory for creation. |
2 | Collation strength defines comparison levels that denote differences between characters. You can configure various options (case-sensitivity, case-ordering, and others), depending on the selected strength. |
3 | Specify whether to compare numeric strings as numbers or as strings. |
4 | Specify whether the collation should consider whitespace and punctuation as base characters for purposes of comparison. |
5 | Specify whether strings with diacritics sort from back of the string, such as with some French dictionary ordering. |
6 | Specify whether to check whether text requires normalization and whether to perform normalization. |
Collations can be used to create collections and indexes. If you create a collection that specifies a collation, the collation is applied to index creation and queries unless you specify a different collation. A collation is valid for a whole operation and cannot be specified on a per-field basis, as the following example shows:
Collation french = Collation.of("fr");
Collation german = Collation.of("de");
template.createCollection(Person.class, CollectionOptions.just(collation));
template.indexOps(Person.class).ensureIndex(new Index("name", Direction.ASC).collation(german));
MongoDB uses simple binary comparison if no collation is specified (Collation.simple() ).
|
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:
find
Collation collation = Collation.of("de");
Query query = new Query(Criteria.where("firstName").is("Amél")).collation(collation);
List<Person> results = template.find(query, Person.class);
aggregate
Collation collation = Collation.of("de");
AggregationOptions options = AggregationOptions.builder().collation(collation).build();
Aggregation aggregation = newAggregation(
project("tags"),
unwind("tags"),
group("tags")
.count().as("count")
).withOptions(options);
AggregationResults<TagCount> results = template.aggregate(aggregation, "tags", TagCount.class);
Indexes are only used if the collation used for the operation matches the index collation. |
JSON Schema
As of version 3.6, MongoDB supports collections that validate documents against a provided JSON Schema. The schema itself and both validation action and level can be defined when creating the collection, as the following example shows:
{
"type": "object", (1)
"required": [ "firstname", "lastname" ], (2)
"properties": { (3)
"firstname": { (4)
"type": "string",
"enum": [ "luke", "han" ]
},
"address": { (5)
"type": "object",
"properties": {
"postCode": { "type": "string", "minLength": 4, "maxLength": 5 }
}
}
}
}
1 | JSON schema documents always describe a whole document from its root. A schema is a schema object itself that can contain embedded schema objects that describe properties and subdocuments. |
2 | required is a property that describes which properties are required in a document. It can be specified optionally, along with other
schema constraints. See MongoDB’s documentation on available keywords. |
3 | properties is related to a schema object that describes an object type. It contains property-specific schema constraints. |
4 | firstname specifies constraints for the firsname field inside the document. Here, it is a string-based properties element declaring
possible field values. |
5 | address is a subdocument defining a schema for values in its postCode field. |
You can provide a schema either by specifying a schema document (that is, by using the Document
API to parse or build a document object) or by building it with Spring Data’s JSON schema utilities in org.springframework.data.mongodb.core.schema
. MongoJsonSchema
is the entry point for all JSON schema-related operations. The following example shows how use MongoJsonSchema.builder()
to create a JSON schema:
MongoJsonSchema.builder() (1)
.required("firstname", "lastname") (2)
.properties(
string("firstname").possibleValues("luke", "han"), (3)
object("address")
.properties(string("postCode").minLength(4).maxLength(5)))
.build(); (4)
1 | Obtain a schema builder to configure the schema with a fluent API. |
2 | Configure required properties. |
3 | Configure the String-typed firstname field, allowing only luke and han values. Properties can be typed or untyped. Use a static import of JsonSchemaProperty to make the syntax slightly more compact and to get entry points such as string(…) . |
4 | Build the schema object. Use the schema to create either a collection or query documents. |
There are already some predefined and strongly typed schema objects (JsonSchemaObject
and JsonSchemaProperty
) available
through static methods on the gateway interfaces.
However, you may need to build custom property validation rules, which can be created through the builder API, as the following example shows:
// "birthdate" : { "bsonType": "date" }
JsonSchemaProperty.named("birthdate").ofType(Type.dateType());
// "birthdate" : { "bsonType": "date", "description", "Must be a date" }
JsonSchemaProperty.named("birthdate").with(JsonSchemaObject.of(Type.dateType()).description("Must be a date"));
CollectionOptions
provides the entry point to schema support for collections, as the following example shows:
$jsonSchema
MongoJsonSchema schema = MongoJsonSchema.builder().required("firstname", "lastname").build();
template.createCollection(Person.class, CollectionOptions.empty().schema(schema));
You can use a schema to query any collection for documents that match a given structure defined by a JSON schema, as the following example shows:
$jsonSchema
MongoJsonSchema schema = MongoJsonSchema.builder().required("firstname", "lastname").build();
template.find(query(matchingDocumentStructure(schema)), Person.class);
The following table shows the supported JSON schema types:
Schema Type | Java Type | Schema Properties |
---|---|---|
|
- |
|
|
|
|
|
any array except |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(none) |
|
|
(none) |
|
|
(none) |
|
|
(none) |
|
|
(none) |
|
|
(none) |
|
|
(none) |
untyped is a generic type that is inherited by all typed schema types. It provides all untyped schema properties to typed schema types.
|
For more information, see $jsonSchema.
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:
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:
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 . |
You can directly apply projections to result documents by providing the target type via as(Class<?>) .
|
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.
|
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 executing a geoNear
command in MongoDB (fetching entities as a GeoResult
within GeoResults
), as the following example shows:
GeoResults<Jedi> results = mongoOps.query(SWCharacter.class)
.as(Jedi.class)
.near(alderaan) // NearQuery.near(-73.9667, 40.78).maxDis…
.all();
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.
Query query = query(where("firstname").is("luke"))
.comment("find luke") (1)
.batchSize(100) (2)
.slaveOk(); (3)
1 | The comment propagated to the MongoDB profile log. |
2 | The number of documents to return in each response batch. |
3 | Allows querying a replica slave. |
On the repository level the @Meta
annotation provides means to add query options in a declarative way.
@Meta(comment = "find luke", batchSize = 100, flags = { SLAVE_OK })
List<Person> findByFirstname(String firstname);
Running an Example
The following example shows how to query by example when using a repository (of Person
objects, in this case):
public interface PersonRepository extends QueryByExampleExecutor<Person> {
}
public class PersonService {
@Autowired PersonRepository personRepository;
public List<Person> findPeople(Person probe) {
return personRepository.findAll(Example.of(probe));
}
}
An Example
containing an untyped ExampleSpec
uses the Repository type and its collection name. Typed ExampleSpec
instances use their type as the result type and the collection name from the Repository
instance.
When including null values in the ExampleSpec , Spring Data Mongo uses embedded document matching instead of dot notation property matching. Doing so forces exact document matching for all property values and the property order in the embedded document.
|
Spring Data MongoDB provides support for the following matching options:
Matching | Logical result |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Untyped Example
By default Example
is strictly typed. This means that the mapped query has an included type match, restricting it to probe assignable types. For example, when sticking with the default type key (_class
), the query has restrictions such as (_class : { $in : [ com.acme.Person] }
).
By using the UntypedExampleMatcher
, it is possible to bypass the default behavior and skip the type restriction. So, as long as field names match, nearly any domain type can be used as the probe for creating the reference, as the following example shows:
class JustAnArbitraryClassWithMatchingFieldName {
@Field("lastname") String value;
}
JustAnArbitraryClassWithMatchingFieldNames probe = new JustAnArbitraryClassWithMatchingFieldNames();
probe.value = "stark";
Example example = Example.of(probe, UntypedExampleMatcher.matching());
Query query = new Query(new Criteria().alike(example));
List<Person> result = template.find(query, Person.class);