Filters and FilterSet
The FilterSet and Filter classes provide a structured and flexible way to define filters for your data retrieval operations. Inspired by Django Rest Framework (DRF) filters, these components allow you to define filtering criteria for database queries. The Filter supports operations like filtering by equality, ranges, inclusion in a set, substring matching, and more, making it highly adaptable to various requirements.
FilterSet Class
The FilterSet class represents a collection of filters. It provides a fluent API for creating and managing filters that can be applied to your data models.
Constructor
FilterSet(): Creates an emptyFilterSet.FilterSet(Set<Filter> filters): Creates aFilterSetwith the given set of filters.
Methods
Set<Filter> getFilters(): Retrieves all filters in theFilterSet.void add(Filter filter): Adds a single filter to theFilterSet.
Builder
The FilterSetBuilder provides methods to construct a FilterSet instance fluently:
protected FilterSet configFilterSet() {
return FilterSet.builder()
.addFilter("nationalNumber", FilterOperation.EQUAL, FieldType.INTEGER)
.addFilter("date_time", "class_date_time", FilterOperation.BETWEEN, FieldType.DATE_TIME)
.build();
}
The example applies set of 2 filters on the endpoint result:
nationalNumber: Checks if thenationalNumberequals to givennationalNumberparameter. Here the endpoint filter parameter will be same as the model field name.
date_time: This filter parameter has a name (date_time) different from the corresponding model field (class_date_time). It is used to check whether the value of theclass_date_timefield of the records falls within a specified datetime range.
Finally we compile the FilterSet by calling .build() method.
Basic Filter:
FilterSetBuilder addFilter(String name, FilterOperation operation, FieldType fieldType)
Adds a filter with a name, operation, and type.
Filter with Help Text:
FilterSetBuilder addFilter(String name, FilterOperation operation, FieldType fieldType, String helpText)
Adds a filter and a descriptive help text.
Model-Field Mapping:
FilterSetBuilder addFilter(String name, String modelFieldName, FilterOperation operation, FieldType fieldType)
Links a filter name to a specific model field.
Filter
The Filter class represents an individual filtering criterion. It encapsulates the details required for filtering, such as the field name, filtering operation, field type, and optional help text.
Filter class properties:
String name: The filter’s name (e.g.,id,name).String modelFieldName: The mapped model field name (e.g.,country__name).FilterOperation operation: The filtering operation.FieldType fieldType: The type of the field being filtered (e.g.,STRING,INTEGER).String helpText: A description of the filter’s purpose (optional).boolean required: Make the filter manadatory. Default tofalse.
FilterOperation
The FilterOperation enum defines the types of filtering operations supported:
EQUAL: Checks for equality.GREATER: Filters values greater than the given input.GREATER_OR_EQUAL: Filters values greater than or equal to the input.LESS: Filters values less than the given input.LESS_OR_EQUAL: Filters values less than or equal to the input.BETWEEN: Filters values between two inputs.CONTAINS: Checks if the field contains the given substring.IN: Filters values that are part of a given set.
The filtering system supports querying nested model fields by mapping filter names to specific paths in related models. For example, the continent filter (mapped to country__continent__name) allows you to check if a substring is present in the name field of the continent model, which is linked through the country model. This enables seamless filtering across relationships in a structured and intuitive manner.
protected FilterSet configFilterSet() {
return FilterSet.builder()
.addFilter("name", FilterOperation.CONTAINS, FieldType.STRING, "Check containing a name")
.addFilter("continent", "country__continent__name", FilterOperation.CONTAINS, FieldType.STRING, "Check containing a continent name")
.addFilter("number_of_people", "population", FilterOperation.BETWEEN, FieldType.INTEGER, "Retrieves cities with population between provided population range")
.build();
}
In the example the continent (mapped to country__continent__name): Checks for a substring in related model country’s continent’s ‘name.
Other filters:
name: Checks if the name contains a substring.
number_of_people(mapped topopulation): Filters cities within a specific population range in specific continent.
In this example the presence of filter paramters are optional, so the endpoint can be called like this to query the database records:
curl -X GET "http://localhost:8080/cities?continent=Europe&number_of_people_from=140000&number_of_people_to=250000"