Queries & @Query
Spring Data MongoDB offers three ways to query: derived methods parsed from method names, the @Query annotation carrying raw JSON, and the Criteria API on MongoTemplate. This page shows when to reach for each, plus projections, sorting, and regex.
Derived query methods
The simplest queries come straight from the method name. Spring translates findBy + property + keyword into a MongoDB filter.
public interface ProductRepository extends MongoRepository<Product, String> {
List<Product> findByCategory(String category);
List<Product> findByPriceBetween(BigDecimal min, BigDecimal max);
List<Product> findByCategoryAndPriceLessThan(String category, BigDecimal max);
List<Product> findByNameStartingWith(String prefix);
}
| Method | Generated filter |
|---|---|
findByCategory | { "category": ?0 } |
findByPriceBetween | { "price": { "$gte": ?0, "$lte": ?1 } } |
findByNameStartingWith | { "name": { "$regex": "^?0" } } |
JSON queries with @Query
When the filter is awkward to express as a method name, write the raw MongoDB JSON. Placeholders ?0, ?1 bind method parameters by position.
public interface ProductRepository extends MongoRepository<Product, String> {
@Query("{ 'category': ?0, 'price': { $lte: ?1 } }")
List<Product> findAffordable(String category, BigDecimal maxPrice);
@Query("{ 'tags': { $in: ?0 } }")
List<Product> findByAnyTag(List<String> tags);
@Query("{ 'price': { $gt: ?0 } }")
long countPricierThan(BigDecimal floor);
}
Tip: Use
@Query(count = true)to return a count, and@Query(delete = true)to delete matching documents instead of returning them.
Field projection
Fetch only the fields you need by listing them in the @Query fields attribute — 1 includes, 0 excludes. This reduces payload size and is independent of the filter.
@Query(value = "{ 'category': ?0 }", fields = "{ 'name': 1, 'price': 1 }")
List<Product> findNameAndPriceByCategory(String category);
That returns documents shaped like this (note _id is included unless excluded):
{ "_id": "65f1c2a8e4b0a1d2c3e4f567", "name": "Keyboard", "price": 79.99 }
For type-safe projections, you can also return an interface or DTO projection. See JPA Projections for the same pattern applied to relational data.
Sorting and pagination
Add a trailing Sort or Pageable parameter to any query method — including @Query methods — and Spring applies it.
List<Product> findByCategory(String category, Sort sort);
Page<Product> findByCategory(String category, Pageable pageable);
var page = repository.findByCategory(
"peripherals",
PageRequest.of(0, 20, Sort.by("price").descending()));
See Pagination & Sorting for the full Page/Slice story.
Regex matching
For case-insensitive or pattern matching, either use a derived Containing/Like keyword or a $regex in @Query.
// Derived: case-insensitive substring
List<Product> findByNameContainingIgnoreCase(String fragment);
// @Query with a case-insensitive regex ('i' option)
@Query("{ 'name': { $regex: ?0, $options: 'i' } }")
List<Product> searchByName(String pattern);
Warning: A
$regexthat is not anchored to the start of the value (^...) cannot use an index and forces a collection scan. Anchor your patterns or maintain a dedicated text index for search-heavy fields.
Criteria queries with MongoTemplate
When the filter is built dynamically at runtime, the Criteria API on MongoTemplate is the cleanest choice.
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;
public List<Product> search(String category, BigDecimal maxPrice, String nameFragment) {
Criteria criteria = where("category").is(category);
if (maxPrice != null) {
criteria.and("price").lte(maxPrice);
}
if (nameFragment != null) {
criteria.and("name").regex(nameFragment, "i");
}
return mongoTemplate.find(query(criteria), Product.class);
}
This is impossible to express cleanly as a single derived method — the Criteria API shines when the set of conditions varies per request.
Choosing an approach
| Approach | Best for |
|---|---|
| Derived methods | Simple, fixed filters |
@Query JSON | Operators awkward in method names; projections |
Criteria (MongoTemplate) | Dynamic, runtime-assembled filters |