AlphaAlpha Docs

Dynamic Search

How to use the dynamic search endpoints available on all CRUD resources.

Dynamic Search

Every resource that extends the base CRUD controller exposes two dynamic search endpoints:

  • GET /{resource}/dynamic-search — query parameters
  • POST /{resource}/dynamic-search — request body

Both return a paginated Page<T> response.

Query Parameters (GET)

ParameterTypeDefaultDescription
pageinteger0Zero-based page number
sizeinteger20Results per page (max 100)
searchstring[][]Search criteria in field:value format
filtersstring[][]Filter criteria (see Filter Operators)
sortstringSort expression (see Sorting)

Example

GET /products/dynamic-search?search=name:table&search=id:table&filters=status:active&sort=created:desc&page=0&size=20

Request Body (POST)

{
  "search": ["name:table", "id:table"],
  "filters": {
    "status": "active",
    "subsidiaryId": "SUB-001"
  },
  "sort": [
    { "field": "created", "ascending": false }
  ],
  "page": 0,
  "size": 20
}

The POST variant accepts filters as a map (key-value object) and sort as a list of objects with field and ascending properties.

The search parameter accepts an array of strings in field:value format. Each entry tells the backend which field to search and what text to look for.

search=name:wooden table&search=id:wooden table

This searches for "wooden table" in both the name and id fields.

How matching works

  • Multiple search entries are combined with OR — a result matches if any field contains the text.
  • Multi-word values use AND within the field — all words must appear (in any order).
  • Matching is case-insensitive and uses regex.

For example, search=name:oak table matches products where the name contains both "oak" and "table" (e.g. "Solid Oak Dining Table").

Filter Operators

Filters support exact matching and comparison operators.

Simple filter

filters=status:active

Matches documents where status equals "active".

Operator filter

Use the three-part format field:operator:value:

OperatorAliasesDescriptionExample
inMatch any value in a comma-separated liststatus:in:active,pending,draft
gte>=Greater than or equalprice:gte:100
lte<=Less than or equalprice:lte:500
gt>Greater thanquantity:gt:0
lt<Less thanquantity:lt:50

Value coercion

Filter values are automatically coerced:

InputCoerced type
"null"null
"true" / "false"Boolean
"42"Integer
"3.14"Double
anything elseString

Combining filters

Filters are combined with AND — all filters must match. Filters and search are also combined with AND.

filters=status:active&filters=price:gte:100&search=name:chair

This returns items where status is active AND price >= 100 AND name contains "chair".

Sorting

Single sort

sort=created:desc

Direction defaults to ascending if omitted:

sort=name

Multiple sorts

Separate multiple sort expressions with a semicolon:

sort=status:asc;created:desc

Response

All dynamic search endpoints return a standard Spring Page<T>:

{
  "content": [...],
  "totalElements": 142,
  "totalPages": 8,
  "number": 0,
  "size": 20
}

CSV Export

The same parameters work with the CSV export endpoint:

GET /{resource}/csv-export?search=name:table&filters=status:active&sort=created:desc

This returns a ByteArray response with Content-Type: text/csv.

Frontend Helpers

The frontend provides helper functions to build dynamic search parameters from table UI state.

tableDynamicSearchBuilder

Converts table pagination state into API query parameters.

import { tableDynamicSearchBuilder } from "@/shared/components/table/functions/tableDynamicSearchBuilder";

const params = tableDynamicSearchBuilder<Product>(
  updater,                    // pagination state from table
  ["name", "id"],             // fields to search
  { status: "active" }        // optional filters
);
// Result: { page, size, search: ["name:text", "id:text"], sort, filters, direction }

dynamicSearchFilterBuilder

Converts a filter object into the string[] format.

import { dynamicSearchFilterBuilder } from "@/shared/functions/shared/dynamicSearchFilterBuilder";

const filters = dynamicSearchFilterBuilder<Product>({
  status: "active",
  category: "furniture",
  name: "",          // empty values are excluded
});
// Result: ["status:active", "category:furniture"]

extractSearchText

Extracts the original search text from a dynamic search array (useful for populating the search input).

import { extractSearchText } from "@/shared/components/table/functions/tableDynamicSearchBuilder";

extractSearchText(["name:wooden table", "id:wooden table"]);
// Result: "wooden table"

Route integration

Routes validate search params using the dynamicPaginationSchema:

import { dynamicPaginationSchema } from "@/shared/schemas/shared";

export const Route = createFileRoute("/_app/products/")({
  validateSearch: z.object({
    page: dynamicPaginationSchema,
  }),
});

On this page