Search and sorting
Every @expose entity gets a search DTO (XxxSrchDTO) and POST /api/<domain>/<entity>/search.
A field's @search(condition) decides how it is searched (@s, @srch and @filter are the same);
a second value after a comma names the entity field (@search(like,comName)).
{ "name": "fish", "pageNumber": 0, "pageSize": 20, "sortCode": "name+" }
The answer is a page: content, totalElements, totalPages, number. pageNumber starts at 0.
Conditions
| DSL | Criteria | Ignores case | Means |
|---|---|---|---|
eq, = | equal | no | exact match |
like | like (%v%) | v3: yes / 2.x-compatible: no | part of the value |
%_%, %% | like (%v%) | no | part of the value, case kept - every mode |
%__% | like (%v%) | yes | part of the value, case ignored |
__=, =__ | equal | yes | exact, case ignored |
_% / %_ | like (v% / %v) | no | starts with / ends with |
__% / %__ | like | yes | starts with / ends with, case ignored |
>, >=, <, <= | comparisons | no | |
in | .in() | no | one of several values (status: List<Status> @search(in)) |
between, ~ | between | no | <field>From and <field>To |
isnull | isNull / isNotNull | no | empty or not: a <field>Empty: Boolean property (v3 bundles) |
auto (@search alone) | decided at run time | no | text only: like when the value starts or ends with %, otherwise eq |
like ignores case in v3In v3 mode - hexagonal, DDD, -Pv3, every Kotlin build - @search(like) on a text field is the same
as %__%: the value is trimmed and lower-cased (Locale.ROOT), the column compared with lower(...).
{"name":"gold"} finds Goldfish. Layered Java's 2.x-compatible output keeps case. To keep case on v3,
write @search(%_%).
- A
%or_the caller puts in the value stays a wildcard ({"name":"%Puppy%"}). - Not implemented:
!=,neq, the keywordsgt,gte,lt,lte,ilike. An unknown condition searches by equality; v3 warns... is not a search condition, so it searches by equality. - Without
@search, an@exposeentity's text fields getauto, date and time fieldsbetween, other typeseq. betweenon aLocalDateadds a day toTo, so the last day is included.
isnull - is the value empty?
Loan:
fields:
returnedDate: date @readonly @search(isnull) -- returned on, empty until returned
returnedDateEmpty in the request | Condition |
|---|---|
not sent, or null | none |
true | IS NULL - loans not yet returned |
false | IS NOT NULL |
One condition per field: an isnull field gets no From/To. With @ref(order.shippedDate) the
column across the reference is checked. The 2.x generator and the jpa-springboot output treat
isnull as an unknown condition (equality).
A list field
drivers: List<RentDriver> @search(eq) gives driversItem and a join (root.join("drivers"));
@search(in) on a list field joins too.
Across a reference
companyName: string @search(like) @ref(company.name) # r.get("company").get("name")
Default order: @sort
entity:
Product:
meta: entity @root @expose(20) @sort(name+)
PurchaseOrder:
meta: entity @root @expose(20) @sort(orderDate-, orderId-)
The order a search takes when the request sends no sortCode - on the entity for all its search
DTOs, or on a search DTO for that one (the search DTO's wins). The request's sortCode always wins.
Generated: @Builder.Default private String sortCode="name+";. Without @sort a search has no order.
Searching in code
Generated code builds a Specification from the search DTO. In your own code the Q class builds
conditions at run time, with operators the DSL does not have:
Specification<VendorInfo> spec = Q.VendorInfo.vendorName(Op.ILIKE, "acme");
// WHERE LOWER(vendor_name) LIKE LOWER('%acme%')
Op: EQ, NEQ, LIKE (case kept), ILIKE, NOT_LIKE, STARTS_WITH, ENDS_WITH, NOT_ILIKE,
ISTARTS_WITH, IENDS_WITH, IEQ,
GT, GTE, LT, LTE, IN, NOT_IN, IS_NULL, IS_NOT_NULL, BETWEEN. JoinSpec,
UpdateSpec and DeleteSpec build joins, bulk updates and deletes from the same Q metadata; see
blueprint/elasticore-dev-guide.md.