[[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):

.Query by Example using a repository
====
[source, java]
----
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.

NOTE: 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:

[cols="1,2", options="header"]
.`StringMatcher` options
|===
| Matching
| Logical result

| `DEFAULT` (case-sensitive)
| `{"firstname" : firstname}`

| `DEFAULT` (case-insensitive)
| `{"firstname" : { $regex: firstname, $options: 'i'}}`

| `EXACT`  (case-sensitive)
| `{"firstname" : { $regex: /^firstname$/}}`

| `EXACT` (case-insensitive)
| `{"firstname" : { $regex: /^firstname$/, $options: 'i'}}`

| `STARTING`  (case-sensitive)
| `{"firstname" : { $regex: /^firstname/}}`

| `STARTING` (case-insensitive)
| `{"firstname" : { $regex: /^firstname/, $options: 'i'}}`

| `ENDING`  (case-sensitive)
| `{"firstname" : { $regex: /firstname$/}}`

| `ENDING` (case-insensitive)
| `{"firstname" : { $regex: /firstname$/, $options: 'i'}}`

| `CONTAINING`  (case-sensitive)
| `{"firstname" : { $regex: /.\*firstname.*/}}`

| `CONTAINING` (case-insensitive)
| `{"firstname" : { $regex: /.\*firstname.*/, $options: 'i'}}`

| `REGEX`  (case-sensitive)
| `{"firstname" : { $regex: /firstname/}}`

| `REGEX` (case-insensitive)
| `{"firstname" : { $regex: /firstname/, $options: 'i'}}`

|===

[[query-by-example.untyped]]
== 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:

.Untyped Example Query
====
[source, java]
----

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);
----
====

[NOTE]
====
`UntypedExampleMatcher` is likely the right choice for you if you are storing different entities within a single collection or opted out of writing <<mongo-template.type-mapping,type hints>>.

Also, keep in mind that using `@TypeAlias` requires eager initialization of the `MappingContext`. To do so, configure `initialEntitySet` to to ensure proper alias resolution for read operations.
====
