Skip to main content

Builder API

Query​

The builder generates Elasticsearch Query DSL. Supply DSL through applySelect for computed results and aggregates, not SQL functions. For example, to count matching records:

lambda.query(UserInfo.class)
.applySelect("{\"aggs\":{\"count\":{\"filter\":{\"match_all\":{}}}}}")
.queryForMapList();

See Query Operations for field selection and result reading.

Pagination​

Ordinary queries use from and size; a separate count request obtains the total. The builder does not automatically replace deep paging with Scroll or search_after.

Grouped queries use composite aggregation with after_key paging. See Pagination for limits, count meanings, and usage.

Where Builder​

Matching conditions generated by eq still follow the field mapping. Store exact business identifiers in keyword fields; do not expect an analyzed text field to behave like ordinary string equality.

Null inside NOT IN does not have SQL's three-valued semantics. To exclude both a specified age and null fields, remove nulls from the input collection and use isNotNull explicitly:

lambda.query(UserInfo.class)
.notIn(UserInfo::getAge, List.of(20))
.isNotNull(UserInfo::getAge)
.queryForList();

Predicate Values​

text and keyword have no write-time length constraint equivalent to VARCHAR(100). Long strings remain intact in _source; the builder does not truncate or validate their length.

ignore_above affects indexing, not write acceptance. Validate business length limits before writing.

Group By​

groupBy maps to Elasticsearch aggregation. Expressions in applySelect must also use aggregation DSL, not SQL such as SUM(age). For example, count rows by age:

lambda.query(UserInfo.class)
.applySelect("{\"aggs\":{\"cnt\":{\"filter\":{\"match_all\":{}}}}}")
.groupBy("age")
.queryForMapList();

Use aggregation-capable fields, such as numeric or keyword fields.