[[query-by-example.execution]]
== Executing an example

.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` use their type as result type and the collection name from the Repository.

NOTE: When including `null` values in the `ExampleSpec` Spring Data Mongo uses embedded document matching instead of dot notation property matching. This 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 the mapped query will have a type match included restricting it to probe assignable types. Eg. when sticking with the default type key `_class` the query has restrictions like `_class : { $in : [ com.acme.Person] }`.

By using the `UntypedExampleMatcher` it is possible bypasses 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.

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