Chaturmind
LearnDSASystem DesignBlogPremium
Sign inGet started
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML

Company

  • Blog
  • Premium
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← MongoDB & NoSQL Design

NoSQL Fundamentals

  • SQL vs NoSQL Trade-offs
  • Spring Data MongoDB

Advanced MongoDB

  • Indexing & Performance
  • Aggregation Pipeline
  • Schema Design Patterns
Chaturmind
← MongoDB & NoSQL Design

NoSQL Fundamentals

  • SQL vs NoSQL Trade-offs
  • Spring Data MongoDB

Advanced MongoDB

  • Indexing & Performance
  • Aggregation Pipeline
  • Schema Design Patterns
HomeLearnSpring BootSpring Boot REST API DevelopmentData & Persistence
✓ FreeIntermediate· 15 min read

Spring Data MongoDB

@Document, MongoRepository, custom queries — MongoDB persistence in Spring.

Published February 15, 2025


Spring Data MongoDB

Spring Data MongoDB maps Java objects to MongoDB documents and generates repository methods from method names.

Define a document

@Document("products")
@CompoundIndexes({
    @CompoundIndex(def = "{'category': 1, 'status': 1, 'sortOrder': 1}")
})
public class Product {
    @Id
    private String id;

    @Indexed(unique = true)
    private String slug;

    private String name;
    private String category;
    private BigDecimal price;
    private ProductStatus status;

    @CreatedDate
    private Instant createdAt;

    @LastModifiedDate
    private Instant updatedAt;

    @Version
    private Long version; // optimistic locking
}

Repository — zero-boilerplate queries

public interface ProductRepository extends MongoRepository<Product, String> {
    // Spring Data generates the query from the method name
    Optional<Product> findBySlug(String slug);
    List<Product> findByCategoryAndStatus(String category, ProductStatus status);
    boolean existsBySlug(String slug);
    boolean existsBySlugAndIdNot(String slug, String id);

    Page<Product> findByStatus(ProductStatus status, Pageable pageable);

    // Custom query when method naming isn't expressive enough
    @Query("{ 'price': { $gte: ?0, $lte: ?1 }, 'status': 'ACTIVE' }")
    List<Product> findByPriceRange(BigDecimal min, BigDecimal max);
}

MongoTemplate for complex operations

@Service
public class ProductSearchService {
    private final MongoTemplate mongoTemplate;

    public List<Product> search(String keyword) {
        Query query = new Query(
            new Criteria().orOperator(
                Criteria.where("name").regex(keyword, "i"),
                Criteria.where("description").regex(keyword, "i")
            )
        ).with(Sort.by(Sort.Direction.DESC, "createdAt"));
        return mongoTemplate.find(query, Product.class);
    }
}

Configuration

spring:
  data:
    mongodb:
      uri: mongodb+srv://user:pass@cluster.mongodb.net/mydb?retryWrites=true
      auto-index-creation: true   # creates @Indexed annotations automatically

Interview Tip

Know the difference between @Transient (field not persisted to MongoDB) and @Field("mongoFieldName") (map Java field to a different MongoDB field name).

Also explain optimistic locking: @Version Long version — when two threads read the same document and both try to save, the second save throws OptimisticLockingFailureException because the version has already changed.

Previous

SQL vs NoSQL Trade-offs

Next

Indexing & Performance

AI Tutor

Lesson: Spring Data MongoDB

Quick actions

AI responses can be inaccurate. Verify critical information.