Getting started
This walks through the full path: model a grid’s columns, accept ag-grid’s request, and run it against
Elasticsearch. It mirrors the runnable examples/opensearch-aggrid-demo.
1. Install
Available on Maven Central.
Add the adapter — it pulls in gridlink-core:
Maven
<dependency>
<groupId>io.github.codedogapp</groupId>
<artifactId>gridlink-elasticsearch</artifactId>
<version>0.1.0</version>
</dependency>
Gradle
implementation("io.github.codedogapp:gridlink-elasticsearch:0.1.0")
gridlink-elasticsearch declares spring-data-elasticsearch as provided — your application supplies it.
To determine the version compatible with your Spring Boot app, check Spring’s compatibility matrix
2. Model the grid’s columns
Implement FilterModel with one typed component per filterable column.
filters() maps each component to the document field it targets — the key is a field name,
not a Java name, so a column may filter a differently named field.
public record ProductFilterModel(
FieldFilter name,
FieldFilter category,
DateFieldFilter createdAt
) implements FilterModel {
@Override
public Map<String, ColumnFilter> filters() {
final var columns = new LinkedHashMap<String, ColumnFilter>();
columns.put("name", name); // ag-grid column "name" -> field "name"
columns.put("category", category); // ag-grid column "category" -> field "category"
columns.put("createdAt", createdAt);
return columns;
}
}
- Use
FieldFilterfor text columns,DateFieldFilterfor date columns. - Columns with no active filter arrive as
nulland are ignored. - Return a
LinkedHashMapif a stable column order matters.
3. Accept the request and run the query
GridRequest<F> is generic over your
FilterModel, so ag-grid’s JSON binds straight in. One call —
ElasticsearchQueries.toQuery —
assembles criteria, sort and paging into a CriteriaQuery:
@RestController
@RequiredArgsConstructor
class ProductController {
private final ElasticsearchOperations operations;
@PostMapping("/api/products/query")
GridResponse<Product> query(@RequestBody GridRequest<ProductFilterModel> request) {
SearchHits<Product> hits = operations.search(ElasticsearchQueries.toQuery(request), Product.class);
var rows = hits.getSearchHits().stream().map(SearchHit::getContent).toList();
return new GridResponse<>(rows, hits.getTotalHits());
}
}
GridResponse<T> carries the page of
rows plus lastRow (the total match count) that ag-grid’s infinite model needs to find the end of the
dataset.
4. The wire contract
Request — ag-grid’s row window, sort model and filter model:
{
"startRow": 0,
"endRow": 50,
"sortModel": [
{
"colId": "price",
"sort": "desc"
}
],
"filterModel": {
"name": {
"filterType": "text",
"type": "contains",
"filter": "mac"
}
}
}
Response:
{
"rows": [
/* ... up to 50 Product rows ... */
],
"lastRow": 122
}
Next
- Filtering — every text, number and date filter and the query it produces.
- Sorting & paging — multi-column sort and the row-window → page mapping.
- Elasticsearch adapter — the lower-level
toCriteria/sortsentry points.