On this page
Spring Data MongoDB
Spring Data MongoDB provides repository support and template-based access for MongoDB, treating documents as domain objects.
Setup
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
spring:
data:
mongodb:
uri: mongodb://localhost:27017/myapp
# or individual properties:
# host: localhost
# port: 27017
# database: myapp
Document Entity
@Document(collection = "products")
public class Product {
@Id
private String id;
private String name;
private BigDecimal price;
private List<String> tags;
@Indexed(unique = true)
private String sku;
@CreatedDate
private Instant createdAt;
}
Repository
public interface ProductRepository extends MongoRepository<Product, String> {
List<Product> findByTagsContaining(String tag);
List<Product> findByPriceBetween(BigDecimal min, BigDecimal max);
Optional<Product> findBySku(String sku);
@Query("{ 'name': { $regex: ?0, $options: 'i' } }")
List<Product> searchByName(String keyword);
}
MongoTemplate for Complex Queries
@Service
public class ProductService {
private final MongoTemplate mongoTemplate;
public List<Product> findByTagsAndPriceRange(List<String> tags, BigDecimal maxPrice) {
Query query = new Query();
query.addCriteria(Criteria.where("tags").in(tags)
.and("price").lte(maxPrice));
query.with(Sort.by(Sort.Direction.DESC, "createdAt"));
return mongoTemplate.find(query, Product.class);
}
public void updatePrice(String id, BigDecimal newPrice) {
Query query = Query.query(Criteria.where("id").is(id));
Update update = new Update().set("price", newPrice).currentDate("updatedAt");
mongoTemplate.updateFirst(query, update, Product.class);
}
}
Aggregation Pipeline
Aggregation agg = Aggregation.newAggregation(
Aggregation.match(Criteria.where("category").is("electronics")),
Aggregation.group("brand").avg("price").as("avgPrice").count().as("count"),
Aggregation.sort(Sort.Direction.DESC, "avgPrice")
);
AggregationResults<BrandStats> results = mongoTemplate.aggregate(agg, "products", BrandStats.class);
Indexing
@Document(collection = "events")
@CompoundIndex(def = "{'userId': 1, 'timestamp': -1}")
public class Event {
@Id
private String id;
@Indexed
private Long userId;
private Instant timestamp;
private String type;
}
Transactions (Replica Set Required)
@Transactional
public void transferInventory(String fromId, String toId, int quantity) {
Product from = productRepository.findById(fromId).orElseThrow();
Product to = productRepository.findById(toId).orElseThrow();
from.setStock(from.getStock() - quantity);
to.setStock(to.getStock() + quantity);
productRepository.save(from);
productRepository.save(to);
}
Best Practices
- Design documents around query patterns (denormalize when needed)
- Create indexes for frequently queried fields
- Use
@CompoundIndexfor multi-field queries - Prefer repository methods for simple queries;
MongoTemplatefor complex ones - Use aggregation pipeline for analytics and reporting queries