How do you query documents with MongoTemplate using Query and Criteria?
answer
- Query + Criteria.where().is()
- find/findOne/findById/count
- with(Sort)/skip/limit/fields()
- Java property names → mapped fields
- empty Query = match all
basics
~10 sBuild a Query object with Criteria (the filter conditions), then call mongoTemplate.find(query, EntityClass.class). Criteria.where("field").is(value) builds the filter; find returns a List of mapped objects.
solid answer
~30 sMongoTemplate is Spring's lower-level MongoDB API. You build a org.springframework.data.mongodb.core.query.Query and attach filter conditions with Criteria: Criteria.where("status").is("ACTIVE").and("age").gte(18). Then mongoTemplate.find(query, Person.class) runs the query and maps each BSON document to a Person via the mapping layer. Use findOne for a single result, findById for the _id, and count/exists for existence. Query also carries pagination and sorting: query.with(Sort.by("name")).skip(20).limit(10), plus field projection via query.fields().include(...). Criteria methods mirror Mongo operators — is/ne/gt/gte/lt/lte/in/nin/regex/exists. Field names use the Java property names, which Spring translates to the stored field names (respecting @Field). MongoTemplate gives you fine control when derived @Repository query methods aren't expressive enough.
code
java · 13 linesimport static org.springframework.data.mongodb.core.query.Criteria.where;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.domain.Sort;
Query query = new Query(
where("status").is("ACTIVE")
.and("age").gte(18))
.with(Sort.by(Sort.Direction.ASC, "lastName"))
.limit(20);
query.fields().include("firstName").include("lastName");
List<Person> adults = mongoTemplate.find(query, Person.class);
long count = mongoTemplate.count(new Query(where("status").is("ACTIVE")), Person.class);go deeper
Should build a basic Query with Criteria.where().is() and call find; knows find vs findOne.
Adds sorting/paging/projection, orOperator composition, and understands property-to-field mapping.
Discusses determinism of findOne, deep-paging cost, and when to prefer MongoTemplate over derived repository methods.
Frames MongoTemplate as the escape hatch below repositories; weighs dynamic-query construction, projection to reduce payload, and exception translation.
**MongoTemplate** is the core class in Spring Data MongoDB for interacting with MongoDB imperatively. It sits below the repository abstraction: repositories generate queries from method names, while MongoTemplate lets you build queries programmatically for full control. It handles connection management, converting between Java objects and BSON documents (the binary JSON format MongoDB stores), and exception translation into Spring's DataAccessException hierarchy. **Query and Criteria.** A `org.springframework.data.mongodb.core.query.Query` object describes what to fetch. You populate it with a `Criteria`, which is a fluent builder for MongoDB filter operators: - `Criteria.where("field")` starts a condition on a field. - `.is(v)` = equality; `.ne(v)` = not-equal; `.gt/.gte/.lt/.lte` = comparisons; `.in(coll)` / `.nin(coll)` = membership; `.regex(pattern)` = pattern match; `.exists(true)` = field presence. - `.and("other")` chains another field condition (implicit logical AND). - Static `new Criteria().orOperator(c1, c2)` / `andOperator(...)` / `norOperator(...)` compose boolean logic across sub-criteria. **Executing.** Common methods: `find(query, Class)` returns a `List`; `findOne(query, Class)` returns the first match or null; `findById(id, Class)`; `findAndModify` / `findAndReplace` for atomic read-modify-write; `count(query, Class)` and `exists(query, Class)`. The second argument (the entity class) drives which collection is targeted (from `@Document(collection=...)` or the class name) and how BSON maps back to objects. **Field name mapping.** In Criteria you use the Java property names. Spring's mapping layer translates them to the persisted field names, honoring `@Field("custom_name")` and `@Id`→`_id`. This is important: if you hand-write the stored name where a `@Field` alias exists, the mapping still works, but mixing the two is a common source of confusion. **Sorting, paging, projection.** `query.with(Sort.by(Sort.Direction.DESC, "createdAt"))`, `query.skip(n)`, `query.limit(n)`, or `query.with(pageable)`. Field projection: `query.fields().include("name").exclude("ssn")` limits which fields come back over the wire. **Edge cases / gotchas.** - `findOne` without a sort returns an arbitrary matching document — add a Sort for determinism. - An empty `Query()` matches everything — `find(new Query(), Person.class)` is a full collection scan. - Criteria is not reusable across mutations in surprising ways; build a fresh one per query to avoid accidental sharing. - Skip/limit paging over large offsets is expensive; prefer range/keyset paging on an indexed field for deep pages. **When to use.** Reach for MongoTemplate when repository derived methods or `@Query` strings are too limited: dynamic/optional filters built at runtime, aggregations, bulk updates, or atomic findAndModify operations.
- What does mongoTemplate.find(new Query(), Person.class) return?Every document in Person's collection mapped to Person objects — an empty Query has no filter, so it is a full collection scan. Add Criteria to filter.
- How do you combine OR conditions in Criteria?Use new Criteria().orOperator(where("a").is(1), where("b").is(2)). The fluent .and(...) chain is always logical AND; boolean composition needs orOperator/andOperator/norOperator.
saying these in an interview costs you the question
- Thinking Criteria.and() means logical OR
- Believing findOne returns a deterministic result without a Sort
- Confusing MongoTemplate with the JPA EntityManager / SQL semantics
- Assuming you must write raw BSON strings — Criteria builds them for you