Skip to main content

QscSearchRequestValidationFilter

This filter validates incoming search requests in the search pipeline. It checks fields, parameters, and filters using configurable rules with a readable string syntax. When validation fails, it returns a structured error response with individual error items.

Rules can be configured in two places:

  1. Pipeline YAML — static rules shared across all search apps
  2. Search config — per-search-app rules configured in the admin

Pipeline rules are applied first, then search config rules.

Base Defaults and Validation

The QscSearchRequestValidationFilter extends SearchQueryValidationFilter from qsf-integration. The base filter applies defaults and validates basic query structure automatically.

Base Defaults

The following defaults are applied to all filters before any validation or configurable rules run:

PropertyDefault
nameset to the filter id
filterTypeterm
filterDataTypestring
filterOperatoror

Base Validation

CheckError
page < 0The page must be >= 0.
rows < 0The rows must be >= 0.
Filter missing idA search filter is missing an id.
term/match filter without valuesThe filter 'x' of type term must have at least one value.
range/slider filter without range valueThe filter 'x' of type range must have a range value or values.
Numeric range with non-parseable valueThe filter 'x' has a non-numeric min value: abc

These defaults and checks always run. No configuration needed.

tip

If you only need the base validation without configurable rules, you can use SearchQueryValidationFilter directly:

- !!com.quasiris.qsf.pipeline.filter.SearchQueryValidationFilter
active: true
id: search-pipeline.SearchQueryValidationFilter

Pipeline Configuration

- !!com.quasiris.qsc.search.service.QscSearchRequestValidationFilter
active: true
id: search-pipeline.QscSearchRequestValidationFilter
rules:
- "locale: required"
- "q: required, minLength=1, maxLength=500"
- "requestId: required"
- "userId: required"
- "sessionId: required"
- "requestOrigin: required"
- "page: min=0, max=100, default=1"
- "rows: min=0, max=100, default=10"

The filter should be placed early in the pipeline, typically after QscSearchQueryFilter and before QueryRuleFilter.

Search Config

Rules can also be configured per search app in the search config via the validation object:

{
"validation": {
"rules": [
"q: required, minLength=1, maxLength=500",
"parameter.customerId: required, type=integer",
"rows: max=50"
]
}
}

Search config rules are merged with pipeline rules at runtime. Pipeline rules run first, then search config rules. The same string syntax applies to both. See the Search Config documentation for details.

Rule Syntax

Each rule is a string with the format:

target: constraint1, constraint2, ...

There are three categories of rules:

CategoryFormatDescription
FieldfieldName: constraintsValidates a standard search query field
Parameterparameter.name: constraintsValidates a parameter from the parameters map
Filterfilter.id: constraintsValidates a search filter from the filter list

Standard fields (q, locale, page, rows, requestId, userId, sessionId, requestOrigin) use no prefix. Only parameter. and filter. require a prefix.

Field Rules

Validate standard fields on the search query.

ConstraintDescriptionExample
requiredField must be non-null and non-blanklocale: required
valuesField value must be one of the listed values (separated by |)locale: values=de|en|fr
minLengthMinimum string lengthq: minLength=1
maxLengthMaximum string lengthq: maxLength=500
minMinimum numeric valuepage: min=0
maxMaximum numeric valuepage: max=100
defaultDefault value if field is null (applied before validation)page: default=1

Supported fields

q, locale, requestId, userId, sessionId, requestOrigin, page, rows

Examples

rules:
- "locale: required, values=de|en|fr"
- "q: required, minLength=1, maxLength=500"
- "page: min=0, max=100, default=1"
- "rows: min=0, max=100, default=10"

Multiple rules can be defined for the same field. Each rule is evaluated independently:

rules:
- "q: required, message=q is required"
- "q: minLength=1, message=The minimum length is 1"
- "q: maxLength=500, message=The maximum length is 500"

Parameter Rules

Validate parameters from the parameters map on the search query. Use the parameter. prefix.

ConstraintDescriptionExample
requiredParameter must be presentparameter.customerId: required
valuesValue must be one of the listed values (separated by |)parameter.sort: values=relevance|price|name
typeData type check: string, integer, long, double, booleanparameter.limit: type=integer
type (array)Append [] to require an array; each element is type-checkedparameter.ids: type=integer[]
patternRegex pattern match (applied per element for arrays)parameter.email: pattern=^[\w@.]+$
defaultDefault value if parameter is missing (applied before validation)parameter.sort: default=relevance

For array parameters, values, type, and pattern constraints are applied to each element individually. Errors include the array index (e.g. parameter.ids[2]).

If type uses [] but the value is not an array, an error is produced. Conversely, if type does not use [] and the value is an array, an error is produced.

Examples

rules:
# single-value parameters
- "parameter.customerId: required, type=integer"
- "parameter.sort: values=relevance|price|name, default=relevance"
- "parameter.email: required, pattern=^[\\w@.]+$"
- "parameter.verbose: type=boolean"

# array parameters
- "parameter.ids: required, type=integer[]"
- "parameter.tags: type=string[], values=featured|sale|new"

Filter Rules

Validate search filters from the filter list. Use the filter. prefix.

info

Basic filter syntax validation (values present for term filters, range value present for range filters, numeric parsing) is already handled by the base SearchQueryValidationFilter. These rules add additional constraints like requiring specific filters or enforcing types.

ConstraintDescriptionExample
requiredFilter must be present in the requestfilter.category: required
valuesEvery filter value must be one of the listed values (separated by |)filter.color: values=red|green|blue
typeExpected filter type: term, match, range, slider, etc.filter.category: type=term
dataTypeExpected data type: string, number, datefilter.price: dataType=number
defaultCreates the filter with this term value if missingfilter.category: default=all
defaultTypeSets filter type if nullfilter.price: defaultType=range
defaultDataTypeSets data type if nullfilter.price: defaultDataType=number
defaultOperatorSets operator if nullfilter.category: defaultOperator=and

Examples

rules:
- "filter.category: required, type=term"
- "filter.price: type=range, dataType=number"

# restrict allowed values
- "filter.color: values=red|green|blue"

# create a default filter if not present in the request
- "filter.status: default=active"

# set default type/dataType on an existing filter
- "filter.price: defaultType=range, defaultDataType=number"

Default Values

Rules can specify default values that are applied before validation runs. This means a field with required and default will never fail the required check -- the default is set first.

Field and Parameter Defaults

Use default=<value> to set a value when the field or parameter is null/missing.

rules:
# field defaults
- "page: min=0, max=100, default=1"
- "rows: min=0, max=100, default=10"
- "locale: required, default=de"

# parameter defaults
- "parameter.sort: default=relevance"
tip

For numeric fields (page, rows), the default value string is parsed as an integer. For locale, it is parsed via Locale.forLanguageTag() (e.g. de, en-US).

Filter Defaults

Filters support several default constraints:

ConstraintDescription
default=<value>If the filter is not present, creates a new term filter with this value
defaultType=<type>Sets the filter type if null (e.g. term, range, slider)
defaultDataType=<type>Sets the data type if null (e.g. string, number, date)
defaultOperator=<op>Sets the operator if null (e.g. or, and)

When default=<value> creates a new filter, it uses term type, string data type, and or operator by default. You can override these with defaultType, defaultDataType, and defaultOperator on the same rule.

rules:
# create a term filter with value "active" if not in the request
- "filter.status: default=active"

# create a range filter with default value
- "filter.price: default=0, defaultType=range, defaultDataType=number"

# set default properties on existing filters (no-op if filter is absent)
- "filter.category: defaultOperator=and"

Custom Messages and Status Codes

Any rule can have an optional message and statusCode:

OptionDescriptionDefault
statusCode=<code>HTTP status code for the error response400
message=<text>Custom error message (replaces the auto-generated one)auto-generated
caution

message= must be the last constraint in the rule, because its value extends to the end of the string and can contain commas.

Examples

rules:
# custom message
- "q: required, message=The search query is required"

# custom status code and message
- "page: min=0, max=100, statusCode=422, message=Page number is out of range"

# message with commas
- "parameter.token: required, statusCode=403, message=Access token is required, please authenticate first"

Error Response

When one or more rules fail, the filter returns a structured error response using the FullValidationMessage format from qsc-dto. Each violation is returned as a separate item in the errors array:

{
"timestamp": "2026-03-09T10:30:00.000Z",
"requestId": "a1b2c3d4-...",
"status": 400,
"errors": [
{
"errorGroup": "field",
"field": "locale",
"message": "The field 'locale' is required.",
"errorCode": "required"
},
{
"errorGroup": "field",
"field": "q",
"message": "The field 'q' is required.",
"errorCode": "required"
}
]
}

Each error includes:

PropertyDescription
errorGroupAlways field
fieldThe target: field name, parameter.name, or filter.id
messageHuman-readable error description (or custom message from rule)
errorCodeConstraint that failed: required, values, minLength, maxLength, min, max, type, dataType, pattern, validation

When a rule specifies a custom message, it replaces the auto-generated one:

{
"timestamp": "2026-03-09T10:30:00.000Z",
"requestId": "a1b2c3d4-...",
"status": 422,
"errors": [
{
"errorGroup": "field",
"field": "q",
"message": "The search query is required",
"errorCode": "required"
}
]
}

Full Example

Pipeline YAML

- !!com.quasiris.qsc.search.service.QscSearchRequestValidationFilter
active: true
id: search-pipeline.QscSearchRequestValidationFilter
rules:
# required fields with allowed values
- "locale: required, values=de|en|fr"
- "q: required, message=The search query is required"
- "q: minLength=1, message=The search query must not be empty"
- "q: maxLength=500, message=The search query is too long"
- "requestId: required"
- "userId: required"
- "sessionId: required"
- "requestOrigin: required"

# paging with defaults
- "page: min=0, max=100, default=1"
- "rows: min=0, max=100, default=10"

# filters
- "filter.category: required, type=term"
- "filter.price: type=range, dataType=number"

Search Config

Additional rules per search app, configured in the admin:

{
"validation": {
"rules": [
"parameter.customerId: required, type=integer, message=A valid customer ID is required",
"rows: max=50",
"filter.status: default=active"
]
}
}