skip to content

Spring Data MongoDB & Redis

The document and key-value modules: MongoDB mapping, templates and aggregation, Redis templates and repositories, Redis as a cache and message bus, and reactive Mongo. Interviewers pick from here when the system design involves something other than a relational store.

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

explore

questions

page 1 of 2

What do @Document, @Id, and @Field do when mapping a Java/Kotlin class to a MongoDB collection with Spring Data MongoDB?

level: juniorimportance: must knowfreq 70%

answer

  1. @Document = collection, default = decapitalized class name
  2. @Id -> _id primary key (ObjectId/String/Long)
  3. @Field renames the stored key
  4. MappingMongoConverter reads the annotations
  5. no auto snake_case / no pluralization

basics

~10 s

@Document marks a class as a MongoDB collection (optionally naming it). @Id marks the field used as MongoDB's _id primary key. @Field maps a Java field to a differently-named document key.

solid answer

~40 s

@Document tells Spring Data MongoDB the class is persistable as a document; @Document(collection = "users") sets the collection name (default is the decapitalized class name). @Id maps a property to MongoDB's mandatory _id key — the primary key; if you use an ObjectId or String field, MongoDB or Spring generates it on insert. @Field customizes how a single property is stored: @Field("first_name") stores the Java property firstName under the document key first_name, letting your Java naming differ from the stored schema. Without @Field the property name is used verbatim. These annotations are read by the MappingMongoConverter, which builds a MongoPersistentEntity model of the class and uses it to convert between org.bson.Document (BSON) and your objects in both directions.

code

java · 18 lines
java
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

@Document(collection = "users")
public class User {

    @Id
    private ObjectId id;            // maps to _id, auto-generated on insert

    @Field("first_name")
    private String firstName;      // stored under key "first_name"

    private String email;          // stored under key "email" (name unchanged)

    // constructors / getters / setters
}

go deeper

for a junior

Know the three annotations and that _id is the primary key.

for a middle

Know default collection naming, id generation, and @Field extras (targetType, write).

for a senior

Explain that MappingMongoConverter/MongoMappingContext read these into a MongoPersistentEntity model.

for a principal

Discuss schema-migration implications of renaming fields and choosing id types for sharding/index behavior.

Spring Data MongoDB maps plain classes (POJOs) to MongoDB documents. A MongoDB **document** is a JSON/BSON object stored inside a **collection** (the rough equivalent of a SQL table). The mapping is driven by annotations in `org.springframework.data.mongodb.core.mapping` and `org.springframework.data.annotation`. ## @Document `@Document` (`org.springframework.data.mongodb.core.mapping.Document`) marks a class as the root of a document. It is optional for the mapping to work but recommended — it lets you set the collection name via `@Document(collection = "users")` (the `value`/`collection` attributes are aliases). - If omitted, the collection name defaults to the **decapitalized simple class name** (class `User` -> collection `user`). - It can also carry a SpEL `#{...}` collection expression and a `language`/`collation` hint. ## @Id `@Id` (`org.springframework.data.annotation.Id`) designates the property that maps to MongoDB's special `_id` field. Every MongoDB document must have an `_id`; it is the primary key and is automatically indexed and unique. - Common id types: `org.bson.types.ObjectId`, `String`, or `Long`. - If the id is `String`/`ObjectId` and is null on insert, Spring/Mongo generates an `ObjectId` value. - Note: a property literally named `id` is also treated as the id even without the annotation. - In the stored document the key is always `_id`, regardless of your Java field name. ## @Field `@Field` (`org.springframework.data.mongodb.core.mapping.Field`) customizes a single property's storage. `@Field("first_name")` (or `@Field(name = "first_name")`) changes the document key. It also supports: - `order`, - `targetType` (e.g. `FieldType.STRING` to store a value as a specific BSON type), - and `write` (e.g. `Field.Write.NON_NULL` to skip writing null fields). Without `@Field`, the Java property name is used as-is (there is no automatic snake_case conversion unless you configure a `FieldNamingStrategy`). ## Who reads these The `MappingMongoConverter` together with `MongoMappingContext`. On startup (or first use) it inspects the class, builds a `MongoPersistentEntity` with `MongoPersistentProperty` entries, and caches it. At runtime it uses that model to convert a domain object to `org.bson.Document` on save and back on read. ## Gotchas and when to use **Gotchas:** - (1) `@Document` collection default is decapitalized, not pluralized — no automatic `s`. - (2) Changing `@Field` names or the id type does **not** migrate existing data — old documents keep their old keys. - (3) A transient field can be excluded with `@Transient`. - (4) The class needs a way to be instantiated (a persistence constructor or a no-arg constructor); Spring can use a parameterized constructor and even bypass setters via field access. **When to use:** - always annotate the id; - use `@Document(collection=...)` when you want an explicit, stable collection name; - use `@Field` when your Java naming should differ from the stored schema (e.g. matching an existing collection).

  • If you omit @Document, is the class still persistable?
    Yes. Mapping works from any POJO; @Document is optional. Without it the collection name defaults to the decapitalized class name. You lose the ability to set an explicit collection name/collation via the annotation.
  • What type does MongoDB generate for an @Id String field that is null on insert?
    An ObjectId is generated and stored in _id; when read back into a String field it is the ObjectId's 24-char hex string. If you need a real ObjectId object, declare the field as ObjectId.

saying these in an interview costs you the question

  • Thinking the default collection name is pluralized (e.g. 'users') — it is the decapitalized class name.
  • Believing @Field auto-converts camelCase to snake_case — it does not; you must name it explicitly or set a FieldNamingStrategy.
  • Claiming @Document is mandatory for persistence.

context

open as a page

What is ReactiveMongoRepository and what do its query methods return?

level: juniorimportance: must knowfreq 70%

basics

~10 s

It is Spring Data's reactive interface for MongoDB. Query methods return Mono<T> for zero-or-one result and Flux<T> for many. Nothing runs until you subscribe.

open as a page

What is a MongoRepository and how do derived (query-method) queries work in Spring Data MongoDB?

level: juniorimportance: must knowfreq 75%

basics

~20 s

MongoRepository is a Spring Data interface for a MongoDB collection giving CRUD out of the box. You add method names like findByLastName, and Spring parses the name into a query automatically — no implementation code needed.

open as a page

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

level: juniorimportance: must knowfreq 70%

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.

open as a page

How does Redis back the Spring Cache abstraction, and what is the role of RedisCacheManager?

level: juniorimportance: must knowfreq 60%

basics

~20 s

RedisCacheManager is the CacheManager implementation that stores cache entries in Redis. When you use @Cacheable, Spring asks it for a RedisCache, which reads/writes values as Redis keys so cached data survives restarts and is shared across instances.

open as a page

What is RedisTemplate (and StringRedisTemplate) in Spring Data Redis, and how do you read/write a value with it?

level: juniorimportance: must knowfreq 70%

basics

~10 s

RedisTemplate is Spring's helper class for talking to Redis. You get an operations object like opsForValue() and call set/get. StringRedisTemplate is a ready-made version where keys and values are Strings.

open as a page

How does the @Query annotation work on a MongoRepository method, and when would you use it over a derived method?

level: middleimportance: must knowfreq 70%

basics

~20 s

@Query lets you write the raw MongoDB query as a JSON filter string on a repository method, with ?0, ?1 placeholders for arguments. Use it when the query is too complex for a readable derived method name.

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 configure TTL, key prefixing, null handling, and serialization for a Redis-backed cache?

level: middleimportance: must knowfreq 65%

basics

~10 s

You build a RedisCacheConfiguration and set options on it: entryTtl(Duration) for expiry, a value serializer (e.g. JSON), disableCachingNullValues(), and a key prefix. You pass it to RedisCacheManager as the default and/or per cache.

open as a page

How do you configure serializers on a RedisTemplate, and why is the choice important?

level: middleimportance: must knowfreq 60%

basics

~10 s

Define a RedisTemplate bean and call setKeySerializer/setValueSerializer (and the hash variants). Common choices: StringRedisSerializer for keys and a JSON serializer for values, so data is readable and language-neutral.

open as a page

How is backpressure handled on a result Flux from a reactive MongoDB query?

level: seniorimportance: must knowfreq 45%

basics

~20 s

The reactive driver honours reactive-streams demand: the subscriber requests N items, and the driver fetches from MongoDB in batches to match, pausing when demand is zero. So a slow consumer naturally throttles the query instead of buffering everything.

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 is @DBRef in Spring Data MongoDB, how does it behave at runtime, and what are its drawbacks versus embedding or manual references?

level: middleimportance: should knowfreq 55%

basics

~20 s

@DBRef stores a link to a document in another collection instead of embedding it. On load, Spring fetches the referenced document with a separate query. It has no cascade and can cause many extra reads (N+1).

open as a page

How do @Indexed and @CompoundIndex work in Spring Data MongoDB, and what governs whether the indexes are actually created?

level: middleimportance: should knowfreq 50%

basics

~10 s

@Indexed declares a secondary index on one field; @CompoundIndex (on the class) declares a multi-field index. Spring only creates them automatically if auto-index-creation is enabled, which is off by default in recent versions.

open as a page

What does @Tailable do on a reactive repository method, and what are its requirements?

level: middleimportance: should knowfreq 45%

basics

~10 s

@Tailable makes a Flux query use a tailable cursor: it stays open and keeps emitting new matching documents as they are inserted, like tail -f. It requires a capped collection and must return Flux.

open as a page

When would you use ReactiveMongoTemplate instead of a ReactiveMongoRepository?

level: middleimportance: should knowfreq 50%

basics

~10 s

Use the repository for simple CRUD and derived queries. Drop to ReactiveMongoTemplate when you need dynamic queries, aggregations, partial updates, upserts, or fine control the repository abstraction cannot express, still returning Mono/Flux.

open as a page

How do you give different caches different TTLs and serializers within a single RedisCacheManager?

level: middleimportance: should knowfreq 40%

basics

~10 s

Build the manager with RedisCacheManager.builder(cf), set a default via cacheDefaults(cfg), then override specific caches with withInitialCacheConfigurations(Map<name, RedisCacheConfiguration>) — each entry a config with its own TTL/serializer.

open as a page

How do @RedisHash entities and Redis repositories work, and how are objects stored?

level: middleimportance: should knowfreq 45%

basics

~20 s

Annotate a class with @RedisHash and give it an @Id field, then declare a CrudRepository for it. Spring stores each object as a Redis hash under a key like keyspace:id, and save/findById/delete work like JPA.

open as a page

What is the MappingMongoConverter and how do you register a custom converter to control how a specific type is stored and read?

level: seniorimportance: should knowfreq 45%

basics

~20 s

MappingMongoConverter is the component that turns your objects into BSON documents and back, using the mapping metadata. For types it can't map well, you write Converter<A,B> pairs and register them via MongoCustomConversions so they take over reading/writing that type.

open as a page

How do reactive change streams work in Spring Data MongoDB, and how do they differ from @Tailable?

level: seniorimportance: should knowfreq 40%

basics

~20 s

changeStream on ReactiveMongoTemplate opens a Flux of change events (insert, update, delete, replace) on any collection, backed by the replica-set oplog. Unlike @Tailable it needs no capped collection, sees all operation types, and supports resume tokens.

open as a page

Explain the @Aggregation annotation on a MongoRepository — how pipeline methods work and their key features.

level: seniorimportance: should knowfreq 55%

basics

~20 s

@Aggregation lets a repository method run a MongoDB aggregation pipeline. You supply an array of pipeline stage strings ($match, $group, $sort, ...) with ?0 placeholders, and Spring maps each output document to the method's return type.

open as a page

How do geospatial Near queries work in a Spring Data MongoDB repository — the Near/Within keywords, index requirement, and GeoResults?

level: seniorimportance: should knowfreq 40%

basics

~20 s

You add a derived method with the Near keyword taking a Point and a Distance, e.g. findByLocationNear(Point p, Distance d). The location field needs a geospatial index (@GeoSpatialIndexed), and returning GeoResults gives each hit's distance.

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

How do you implement Redis pub/sub messaging in Spring using RedisMessageListenerContainer?

level: seniorimportance: should knowfreq 45%

basics

~10 s

Publish with redisTemplate.convertAndSend(channel, message). To receive, register a RedisMessageListenerContainer bean, give it the connection factory, and addMessageListener(listener, topic) where the listener implements MessageListener (often via a MessageListenerAdapter that delegates to a POJO).

open as a page

How do secondary indexes (@Indexed) enable derived queries on Redis repositories, and what are the costs?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Add @Indexed to a field; Spring keeps a Redis SET of ids per field value (like people:firstname:Ann). Then a derived finder such as findByFirstname reads that set. Without @Indexed you can't query by that field.

open as a page

You run a reactive change-stream listener as a long-lived Flux in production. What failure modes and design concerns must you address?

level: principalimportance: should knowfreq 25%

basics

~20 s

Handle stream errors with resubscription, persist and resume from tokens for gap-free at-least-once delivery, make handlers idempotent, keep the oplog window larger than max consumer lag, bound backpressure, and coordinate consumers so events are processed once across instances.

open as a page

Across derived queries, @Query, @Aggregation, and MongoTemplate — how do you choose the right query mechanism, and what are the tradeoffs?

level: principalimportance: should knowfreq 45%

basics

~10 s

Use derived methods for simple readable finders, @Query for native JSON filters/projections too complex for a name, @Aggregation for grouping and multi-stage pipelines, and MongoTemplate when the query must be built dynamically at runtime.

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

You run several app instances with local caches plus a shared Redis cache. How do you keep them consistent and resilient to Redis failures?

level: principalimportance: should knowfreq 30%

basics

~20 s

Use Redis as the shared cache (RedisCacheManager) so all instances see the same entries, and broadcast invalidations via pub/sub (RedisMessageListenerContainer) when local near-caches must be evicted. For failures, wrap the cache with a CacheErrorHandler or circuit breaker so Redis outages degrade to the DB instead of erroring.

open as a page

Explain how MappingMongoConverter instantiates and populates entities on read, and the role of the _class type hint and persistence constructor. What edge cases arise?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

On read, MappingMongoConverter picks a persistence constructor (or default), maps constructor args from document fields, then sets remaining properties by field access. It writes a _class type hint so polymorphic/abstract types can be reconstructed. Immutable objects and missing/extra fields are the main edge cases.

open as a page

showing 1–30 of 31