SkillAgentSearch skills...

Springfilter

Dynamically filter JPA entities, Mongo collections, and Java in-memory objects with a user-friendly query syntax. Seamless integration with Spring APIs. Star to support the project! ❤️

Install / Use

/learn @turkraft/Springfilter
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Spring Filter

<p align="center"> <a href="https://github.com/turkraft/springfilter"> <img src="https://raw.githubusercontent.com/turkraft/springfilter/main/.github/logo.png?raw=true" alt="Spring Filter Logo"> </a> </p>

Dynamic query filtering for Spring applications. Pass filter expressions as URL parameters and apply them to JPA repositories, MongoDB collections, or in-memory Java objects.

The library parses filter expressions into abstract syntax trees, then converts them to JPA Criteria queries, MongoDB queries, or Java Predicates depending on your module. You can also use the filter builder to construct queries programmatically.

<details> <summary>:warning: <b><u>About Release 3.0.0</u></b></summary>

Spring Filter 3.0.0 is a new release built from the ground up. It includes much better integration with Spring, with many new features, enhancements and bug fixes. The language syntax didn't change, frontend applications will therefore not require any modification. The new FilterBuilder class is incompatible with the previous one and other breaking changes are present but the basic usage of the library remains similar. Please feel free to create an issue if you notice anything wrong. Consider supporting the project by sponsoring us.

You can access the older version in the 2.x.x branch.

</details>

Example (try it live)

/search?filter= average(ratings) > 4.5 and brand.name in ['audi', 'land rover'] and (year > 2018 or km < 50000) and color : 'white' and accidents is empty

@Entity public class Car {
  @Id long id;
      int year;
      int km;
  @Enumerated Color color;
  @ManyToOne Brand brand;
  @OneToMany List<Accident> accidents;
  @ElementCollection List<Integer> ratings;
}

The library handles booleans, dates, enums, functions, and entity relations. JPA module generates criteria queries, MongoDB module generates aggregation pipelines, and predicate module filters in-memory objects.

Sponsors

Sponsor our project and have your issues prioritized.

<table> <tr> <td><a href="https://github.com/ixorbv"><img width="64" src="https://avatars.githubusercontent.com/u/127401397?v=4"/></a></td> </tr> </table>

Modules

JPA

Filter JPA entities directly in database queries. The module converts filter expressions to JPA Criteria API specifications.

<dependency>
  <groupId>com.turkraft.springfilter</groupId>
  <artifactId>jpa</artifactId>
  <version>3.2.5</version>
</dependency>
@GetMapping("/cars")
Page<Car> search(@Filter Specification<Car> spec, Pageable page) {
    return repository.findAll(spec, page);
}

The repository must implement JpaSpecificationExecutor. SimpleJpaRepository is a standard implementation. Remove the Pageable argument if you don't need pagination.

JPA with Native Queries

@GetMapping("/cars/native")
List<Car> searchNative(@Filter Specification<Car> spec) {
    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<Car> query = cb.createQuery(Car.class);
    Root<Car> root = query.from(Car.class);

    query.where(spec.toPredicate(root, query, cb));

    return entityManager.createQuery(query).getResultList();
}

JPA with Projections

@GetMapping("/cars/summary")
List<CarSummary> searchProjection(@Filter Specification<Car> spec) {
    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<CarSummary> query = cb.createQuery(CarSummary.class);
    Root<Car> root = query.from(Car.class);

    query.select(cb.construct(CarSummary.class,
        root.get("brand").get("name"),
        cb.count(root)));
    query.where(spec.toPredicate(root, query, cb));
    query.groupBy(root.get("brand").get("name"));

    return entityManager.createQuery(query).getResultList();
}

MongoDB

Filter MongoDB documents using Spring Data MongoDB queries.

<dependency>
  <groupId>com.turkraft.springfilter</groupId>
  <artifactId>mongo</artifactId>
  <version>3.2.5</version>
</dependency>
@GetMapping("/cars")
Page<Car> search(@Filter(entityClass = Car.class) Query query, Pageable page) {
    return mongoTemplate.find(query.with(page), Car.class);
}

With MongoRepository

public interface CarRepository extends MongoRepository<Car, String> {
  @Query("?0")
  List<Car> findAll(Document document);

  @Query("?0")
  Page<Car> findAll(Document document, Pageable pageable);
}

@GetMapping("/cars")
Page<Car> search(@Filter(entityClass = Car.class) Document document, Pageable page) {
    return repository.findAll(document, page);
}

Predicate

Filter in-memory collections using Java Predicates. Works with any POJO, no database required.

<dependency>
  <groupId>com.turkraft.springfilter</groupId>
  <artifactId>predicate</artifactId>
  <version>3.2.5</version>
</dependency>
@GetMapping("/cars")
List<Car> search(@Filter Predicate<Car> predicate) {
    List<Car> allCars = loadCarsFromCache();
    return allCars.stream()
        .filter(predicate)
        .collect(Collectors.toList());
}

Manual Conversion

@Autowired FilterPredicateConverter converter;

public List<Car> filterCars(List<Car> cars, String filterExpression) {
    FilterPredicate<Car> predicate = converter.convert(filterExpression, Car.class);

    return cars.stream()
        .filter(predicate)
        .collect(Collectors.toList());
}

Use Cases

The predicate module is useful when:

  • Filtering cached data in memory
  • Filtering API responses before returning to client
  • Testing filter logic without database
  • Filtering configuration objects or enums
  • Processing batch data in memory
@GetMapping("/cars/cached")
List<Car> searchCached(@Filter Predicate<Car> predicate) {
    return cacheService.getAllCars().stream()
        .filter(predicate)
        .collect(Collectors.toList());
}

@GetMapping("/cars/filter-after-fetch")
List<Car> filterAfterFetch(@Filter Predicate<Car> predicate) {
    List<Car> cars = externalApiClient.fetchAllCars();
    return cars.stream()
        .filter(predicate)
        .collect(Collectors.toList());
}

Size Function Support

// Filter by collection size
GET /cars?filter=size(accidents) > 2
GET /owners?filter=size(cars) : 0

The predicate module supports all standard operators and the size() function for collections, arrays, maps, and strings.

Filter Builder

Build filter expressions programmatically instead of writing filter strings manually.

<dependency>
  <groupId>com.turkraft.springfilter</groupId>
  <artifactId>core</artifactId>
  <version>3.2.5</version>
</dependency>
@Autowired FilterBuilder fb;

FilterNode filter = fb.field("year").equal(fb.input(2025))
    .and(fb.field("category").isNull())
    .get();

@Autowired ConversionService cs;
String query = cs.convert(filter, String.class);
// year : 2025 and category is null

Complex Queries

FilterNode filter = fb.field("brand.name").in(
    fb.collection(fb.input("audi"), fb.input("bmw"))
).and(
    fb.field("year").greaterThan(fb.input(2020))
        .or(fb.field("km").lessThan(fb.input(50000)))
).get();

With Functions

@Autowired SizeFunction sizeFunction;

FilterNode filter = fb.function(sizeFunction, fb.field("accidents"))
    .greaterThan(fb.input(2))
    .and(fb.field("year").lessThan(fb.input(2015)))
    .get();

OpenAPI/Swagger

Add automatic Swagger documentation for endpoints with @Filter parameters.

<dependency>
  <groupId>com.turkraft.springfilter</groupId>
  <artifactId>openapi</artifactId>
  <version>3.2.5</version>
</dependency>

Just add the dependency. Swagger UI automatically shows:

  • All filterable fields with types
  • Nested relations
  • Enum values
  • Example queries
  • Operator reference
  • Available functions

Works with JPA, MongoDB, and Predicate modules.

Pagination, Sorting and Field Selection

The page-sort module provides annotations for pagination, sorting, and field selection.

<dependency>
  <groupId>com.turkraft.springfilter</groupId>
  <artifactId>page-sort</artifactId>
  <version>3.2.5</version>
</dependency>

Basic Usage

@GetMapping("/cars")
Page<Car> search(@Filter Specification<Car> spec, @Pagination Pageable page) {
    return repository.findAll(spec, page);
}

Usage: ?page=0&size=20&sort=-year (prefix - for descending)

Custom Parameter Names

@GetMapping("/cars")
Page<Car> search(
    @Pagination(pageParameter = "p", sizeParameter = "limit", sortParameter = "order") Pageable page) {
    return repository.findAll(page);
}

Now use ?p=0&limit=50&order=-year

Sort Parameter

@GetMapping("/cars")
List<Car> search(@Sort org.springframework.data.domain.Sort sort) {
    return repository.findAll(sort);
}

Use ?sort=-year or ?sort=-year,name

Field Selection

@Fields
@GetMapping("/cars")
List<Car> search() {
    return repository.findAll();
}

Use ?fields=id,brand.name,year to return only specified fields. Uses Jackson's filtering internally.

// Include specific fields
?fields= id,name,email

// Exclude fields
?fields= *,-password,-ssn

// Nested fields
?fields= id,brand.name,brand.country

// Wildcards
?fields= user.*

Combined Example

@Fields
@GetMapping("/cars")
Page<Car> search(
    @Filter Specification<Car> spec,
    @Pagination Pageable page) {
    return repository.findAll(spec, page);
}

Use all features together:

/cars?filter=year>2020&page=0&size=20&sort=-year&fields=id,brand.name,year

The openapi module automatically genera

Related Skills

View on GitHub
GitHub Stars277
CategoryCustomer
Updated10d ago
Forks36

Languages

Java

Security Score

85/100

Audited on Mar 18, 2026

No findings