Skip to content
Spring Boot sb mongodb 3 min read

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);
}
MethodGenerated 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 $regex that 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

ApproachBest for
Derived methodsSimple, fixed filters
@Query JSONOperators awkward in method names; projections
Criteria (MongoTemplate)Dynamic, runtime-assembled filters
Last updated June 13, 2026
Was this helpful?