skip to content

MongoTemplate & Aggregation

MongoTemplate gives you Criteria-based queries and updates plus the aggregation pipeline — match, group, project, unwind, lookup. Aggregation questions are how interviewers test whether you can do analytics in Mongo rather than in application code.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

How do you query documents with MongoTemplate using Query and Criteria?

level: juniorimportance: must knowfreq 70%

answer

  1. Query + Criteria.where().is()
  2. find/findOne/findById/count
  3. with(Sort)/skip/limit/fields()
  4. Java property names → mapped fields
  5. empty Query = match all

basics

~10 s

Build 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 s

MongoTemplate 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 lines
java
import 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

for a junior

Should build a basic Query with Criteria.where().is() and call find; knows find vs findOne.

for a middle

Adds sorting/paging/projection, orOperator composition, and understands property-to-field mapping.

for a senior

Discusses determinism of findOne, deep-paging cost, and when to prefer MongoTemplate over derived repository methods.

for a principal

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

context

open as a page

What is the difference between updateMulti, updateFirst, insert, and save on MongoTemplate?

level: middleimportance: must knowfreq 62%

basics

~20 s

updateFirst modifies the first matching document, updateMulti modifies all matching ones — both take a Query and an Update with operators like $set. insert always creates a new document; save inserts if new or replaces the whole document if the _id already exists (upsert-by-id).

open as a page

How do you build an aggregation pipeline with match, group, and project stages in Spring Data MongoDB?

level: seniorimportance: must knowfreq 58%

basics

~10 s

Use Aggregation.newAggregation(...) with static stage helpers: match(Criteria) filters, group(fields).sum/count aggregates, project(...) reshapes output. Run it with mongoTemplate.aggregate(agg, "collection", OutputType.class), then read results via getMappedResults().

open as a page

What do the unwind and lookup aggregation stages do, and how do you use them in Spring Data?

level: seniorimportance: should knowfreq 45%

basics

~20 s

unwind flattens an array field: it emits one output document per array element. lookup performs a left-outer join to another collection, adding matched documents as a new array field. In Spring: Aggregation.unwind("items") and Aggregation.lookup("from", "localField", "foreignField", "as").

open as a page

What performance and correctness options matter when running large MongoTemplate aggregations, and how does result mapping work?

level: principalimportance: should knowfreq 30%

basics

~20 s

Filter early with an indexed $match, sort/limit for top-N, and set AggregationOptions.allowDiskUse(true) when $group/$sort exceed the 100 MB in-memory stage limit. Spring maps each result document to your output DTO via getMappedResults; unmatched fields are dropped.

open as a page