Elasticsearch Search Result Customization: Sorting, Pagination, Highlighting, and Java Client Usage

Sorting Search Results

By default, Elasticsearch orders results by relevance score (_score). Custom sorting is supported for fields of type keyword, numeric types, geo_point, and date. Sorting direction is specified using asc or desc.

GET /products/_search
{
  "query": { "match_all": {} },
  "sort": [
    { "category": "asc" },
    { "price": "desc" }
  ]
}

Geospatial sorting uses _geo_distance with a reference point:

GET /stores/_search
{
  "query": { "match_all": {} },
  "sort": [
    {
      "_geo_distance": {
        "location": { "lat": 30.27, "lon": 120.16 },
        "order": "asc",
        "unit": "miles"
      }
    }
  ]
}

Pagination Control

Elasticsearch returns only the first 10 hits by default. To retrieve other result windows, use from (starting offset) and size (number of documents):

GET /products/_search
{
  "query": { "match_all": {} },
  "from": 50,
  "size": 25,
  "sort": [{ "updated_at": "desc" }]
}

Note: Deep pagination (e.g., from > 10,000) incurs high memory and CPU overhead due to how Elasticsearch merges results across shards. For large offsets, prefer search_after or cursor-based navigation.

Result Highlighting

Highlighting wraps matching terms in configurable HTML or plain-text tags. It requires a full-text query (e.g., match, not match_all) and applies only to analyzde fields.

GET /articles/_search
{
  "query": {
    "match": { "content": "distributed search" }
  },
  "highlight": {
    "fields": {
      "content": {
        "pre_tags": ["<strong>"],
        "post_tags": ["</strong>"]
      },
      "title": {}
    }
  }
}

To access highlighted fragments programmatically in Java, extract them from SearchHit.getHighlightFields():

HighlightField titleHighlight = hit.getHighlightFields().get("title");
if (titleHighlight != null) {
    String highlightedTitle = titleHighlight.getFragments()[0].string();
    System.out.println(highlightedTitle);
}

Java REST Client Examples

Basic Match-All Query with Result Parsing

public void executeMatchAll() throws IOException {
    SearchRequest req = new SearchRequest("inventory");
    req.source().query(QueryBuilders.matchAllQuery());

    SearchResponse resp = client.search(req, RequestOptions.DEFAULT);
    SearchHits hits = resp.getHits();
    long totalCount = hits.getTotalHits().value;

    System.out.printf("Total matched: %d\n", totalCount);

    for (SearchHit hit : hits.getHits()) {
        String rawJson = hit.getSourceAsString();
        InventoryItem item = JsonMapper.parse(rawJson, InventoryItem.class);
        System.out.println(item.getName() + " — " + item.getPrice());
    }
}

Multi-Field Full-Text Search

public void executeMultiFieldSearch() throws IOException {
    SearchRequest req = new SearchRequest("inventory");
    req.source()
        .query(QueryBuilders.multiMatchQuery("wireless headset", "name", "description", "tags"))
        .size(15);

    SearchResponse resp = client.search(req, RequestOptions.DEFAULT);
    for (SearchHit hit : resp.getHits().getHits()) {
        System.out.println(hit.getSourceAsString());
    }
}

Boolean Filtering with Range and Term Constraints

public void executeFilteredSearch() throws IOException {
    BoolQueryBuilder filter = QueryBuilders.boolQuery()
        .must(QueryBuilders.termQuery("in_stock", true))
        .filter(QueryBuilders.rangeQuery("rating").gte(4.2))
        .filter(QueryBuilders.rangeQuery("price").lte(199.99));

    SearchRequest req = new SearchRequest("inventory");
    req.source().query(filter).sort("rating", SortOrder.DESC);

    SearchResponse resp = client.search(req, RequestOptions.DEFAULT);
    // process hits...
}

Paginated Sorted Query with Highlighting

public void executePaginatedHighlightedSearch() throws IOException {
    SearchRequest req = new SearchRequest("articles");
    req.source()
        .query(QueryBuilders.matchQuery("body", "cloud infrastructure"))
        .highlighter(new HighlightBuilder()
            .field("title")
            .field("body")
            .preTags("<mark>")
            .postTags("</mark>"))
        .from(0)
        .size(10)
        .sort("published_date", SortOrder.DESC);

    SearchResponse resp = client.search(req, RequestOptions.DEFAULT);
    for (SearchHit hit : resp.getHits().getHits()) {
        Map<String, HighlightField> highlights = hit.getHighlightFields();
        HighlightField titleHl = highlights.get("title");
        if (titleHl != null) {
            System.out.println("Title: " + titleHl.getFragments()[0]);
        }
    }
}

Tags: elasticsearch search Sorting Pagination highlighting

Posted on Wed, 20 May 2026 04:29:30 +0000 by Evanthes