Spring Boot with MongoDB
MongoDB is a document database — no tables, no schemas, just JSON-like documents. Spring Data MongoDB makes it feel just like JPA.
Setup
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
docker run -d --name bookstore-mongo -p 27017:27017 mongo:7
spring:
data:
mongodb:
uri: mongodb://localhost:27017/bookstore
Document Entity
@Document(collection = "books")
public class Book {
@Id
private String id; // MongoDB uses String IDs by default
@Field("title")
@Indexed
private String title;
private String author;
@Indexed(unique = true)
private String isbn;
private BigDecimal price;
private List<String> tags; // arrays
private Map<String, Object> metadata; // nested documents
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
}
Embedded Documents
@Document(collection = "books")
public class Book {
@Id
private String id;
private String title;
private Publisher publisher; // embedded (no separate collection)
private List<Review> reviews; // embedded array
}
// No @Document — this is embedded, not a separate collection
public class Publisher {
private String name;
private String country;
}
public class Review {
private String reviewer;
private int rating;
private String comment;
private LocalDate date;
}
MongoDB document:
{
"_id": "665a...",
"title": "Clean Code",
"publisher": { "name": "Prentice Hall", "country": "US" },
"reviews": [
{ "reviewer": "Alice", "rating": 5, "comment": "Great book!" }
]
}
MongoRepository
public interface BookRepository extends MongoRepository<Book, String> {
List<Book> findByAuthor(String author);
Optional<Book> findByIsbn(String isbn);
List<Book> findByTagsContaining(String tag);
List<Book> findByPriceGreaterThan(BigDecimal price);
Page<Book> findByAuthor(String author, Pageable pageable);
@Query("{ 'title': { $regex: ?0, $options: 'i' } }")
List<Book> searchByTitle(String keyword);
@Query("{ 'reviews.rating': { $gte: ?0 } }")
List<Book> findByMinReviewRating(int minRating);
}
MongoTemplate — Complex Queries
@Service
public class BookService {
private final MongoTemplate mongoTemplate;
public List<Book> searchBooks(String keyword, BigDecimal minPrice) {
Criteria criteria = new Criteria();
if (keyword != null) {
criteria.and("title").regex(keyword, "i");
}
if (minPrice != null) {
criteria.and("price").gte(minPrice);
}
Query query = new Query(criteria).with(Sort.by(Sort.Direction.DESC, "price"));
return mongoTemplate.find(query, Book.class);
}
}
Aggregation
public List<AuthorStats> getAuthorStats() {
Aggregation agg = Aggregation.newAggregation(
Aggregation.group("author")
.count().as("bookCount")
.avg("price").as("avgPrice"),
Aggregation.sort(Sort.Direction.DESC, "bookCount")
);
return mongoTemplate.aggregate(agg, "books", AuthorStats.class)
.getMappedResults();
}
Key Takeaways
@Documentmaps to MongoDB collections (like@Entityfor JPA).- MongoDB uses String IDs and embedded documents instead of joins.
MongoRepositoryworks just likeJpaRepository— derived queries, pagination.- Use
MongoTemplatefor complex queries and aggregations. - Embed related data when it’s always accessed together; reference when it’s independent.
What’s Next?
Next: Spring Boot with Redis — caching, session storage, and @Cacheable.