All Products
Search
Document Center

OpenSearch:Demo code for implementing search features

Last Updated:Apr 01, 2026

This page shows how to implement search using OpenSearch SDK for Java V4.0.0. The examples cover client initialization, query construction (including distinct, aggregation, sort, rank, and summary clauses), and result handling.

Prerequisites

Before you begin, ensure that you have:

Important

Never include your AccessKey pair directly in source code. Store credentials in environment variables to prevent accidental exposure.

Set environment variables

Set the following environment variables with your RAM user's AccessKey ID and AccessKey secret.

Linux and macOS

export ALIBABA_CLOUD_ACCESS_KEY_ID=<access_key_id>
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=<access_key_secret>

Replace <access_key_id> and <access_key_secret> with your actual values.

Windows

  1. Create an environment variable file and add the ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET variables with your AccessKey ID and AccessKey secret as values.

  2. Restart Windows for the variables to take effect.

How it works

The SDK uses a three-layer client structure:

  1. OpenSearch — holds your credentials and endpoint.

  2. OpenSearchClient — wraps OpenSearch and handles HTTP communication.

  3. SearcherClient — built on top of OpenSearchClient; use this to submit search requests.

All search parameters (query, distinct, aggregation, sort, rank, summary) are assembled into a SearchParams object, then run via SearcherClient.

Determine whether a request has failed by checking the error code and message in the response, not the HTTP status. For a full list of error codes, see Error codes.

Initialize the client

Read credentials from environment variables, then initialize the three-layer client. Replace <your-endpoint> with the OpenSearch API endpoint for your region.

package com.aliyun.opensearch;

import com.aliyun.opensearch.sdk.generated.OpenSearch;

public class SearchDemo {

    private static final String APP_NAME = "<your-application-name>";
    private static final String HOST     = "<your-endpoint>";

    public static void main(String[] args) {

        // Read credentials from environment variables
        String accessKey = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        String secret    = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");

        // Build the three-layer client
        OpenSearch       openSearch     = new OpenSearch(accessKey, secret, HOST);
        OpenSearchClient serviceClient  = new OpenSearchClient(openSearch);
        SearcherClient   searcherClient = new SearcherClient(serviceClient);
    }
}

Configure the config clause

The Config object sets paging, result format, and the fields to return.

import com.aliyun.opensearch.sdk.dependencies.com.google.common.collect.Lists;
import com.aliyun.opensearch.sdk.generated.search.Config;
import com.aliyun.opensearch.sdk.generated.search.SearchFormat;

// Attach the application and set paging
Config config = new Config(Lists.newArrayList(APP_NAME));
config.setStart(0);   // starting offset
config.setHits(5);    // results per page

// Result format: XML, JSON, or FULLJSON
config.setSearchFormat(SearchFormat.FULLJSON);

// Fields to include in the response
config.setFetchFields(Lists.newArrayList(
    "id", "name", "phone", "int_arr", "literal_arr", "float_arr", "cate_id"
));

// Note: To ensure accurate total and viewtotal counts when reserved=false in the distinct clause,
// add the duniqfield parameter via the kvpairs clause:
// config.setKvpairs("duniqfield:cate_id");

Set the search query and filter

Build a SearchParams object from the config, then set the query and filter.

import com.aliyun.opensearch.sdk.generated.search.SearchParams;
import com.aliyun.opensearch.search.SearchParamsBuilder;

SearchParams        searchParams  = new SearchParams(config);
SearchParamsBuilder paramsBuilder = SearchParamsBuilder.create(searchParams);

// Query against the "name" index field
searchParams.setQuery("name:'opensearch'");

// Raw query — must match the search query above
searchParams.setRawQuery("opensearch");

// Add a filter condition (AND logic)
paramsBuilder.addFilter("id>=0", "AND");

Configure the distinct clause

Use Distinct to deduplicate results by a specified field.

import com.aliyun.opensearch.sdk.generated.search.Distinct;

Distinct dist = new Distinct();
dist.setKey("cate_id");           // field to deduplicate on
dist.setDistCount(1);             // documents extracted per group
dist.setDistTimes(1);             // number of extraction rounds
dist.setReserved(false);          // discard documents after extraction
dist.setUpdateTotalHit(false);    // do not subtract discarded docs from totalHits
dist.setDistFilter("cate_id<=3"); // apply deduplication only to matching documents
dist.setGrade("1.2");             // deduplication threshold

searchParams.addToDistincts(dist);

Configure the aggregation clause

Use Aggregate to group and count results by a field. Multiple aggregations are supported.

import com.aliyun.opensearch.sdk.generated.search.Aggregate;
import java.util.HashSet;
import java.util.Set;

// Aggregation on a single field (detailed example)
Aggregate agg = new Aggregate();
agg.setGroupKey("cate_id");          // field to group by
agg.setAggFun("count()");            // aggregation function
agg.setAggFilter("cate_id=1");       // pre-aggregation filter
agg.setRange("0~10");                // aggregation range
agg.setAggSamplerThresHold("5");     // sampling threshold
agg.setAggSamplerStep("5");          // sampling step
agg.setMaxGroup("5");                // maximum groups returned

// Aggregation on multiple fields — use a Set<Aggregate>
Set<Aggregate> aggregates = new HashSet<>();

Aggregate agg1 = new Aggregate();
agg1.setGroupKey("cate_id");
agg1.setAggFun("count()");
aggregates.add(agg1);

Aggregate agg2 = new Aggregate();
agg2.setGroupKey("cate_id_1");
agg2.setAggFun("count()");
aggregates.add(agg2);

searchParams.setAggregates(aggregates);

Configure sort and rank

Sort results by one or more fields, then specify rough-sort and fine-sort expressions.

import com.aliyun.opensearch.sdk.generated.search.Sort;
import com.aliyun.opensearch.sdk.generated.search.SortField;
import com.aliyun.opensearch.sdk.generated.search.Order;
import com.aliyun.opensearch.sdk.generated.search.Rank;

// Sort: descending by id, then ascending by RANK for ties
Sort sorter = new Sort();
sorter.addToSortFields(new SortField("id",   Order.DECREASE));
sorter.addToSortFields(new SortField("RANK", Order.INCREASE));
searchParams.setSort(sorter);

// Rank: specify rough-sort and fine-sort expressions
Rank rank = new Rank();
rank.setFirstRankName("default");   // rough-sort expression
rank.setSecondRankName("default");  // fine-sort expression
rank.setReRankSize(5);              // number of candidates for fine sort
searchParams.setRank(rank);

Configure the summary clause

Add a summary (highlight snippet) to text fields in the response. The name field must be of the TEXT type for analysis to work.

// Configure via SearchParamsBuilder (recommended)
paramsBuilder.addSummary(
    "name",  // field name (must be TEXT type)
    50,      // segment length in characters
    "em",    // HTML tag used to highlight matched terms
    "...",   // connector between segments
    1        // number of segments
);

Configure a custom parameter

Pass additional parameters using a map, such as the biz parameter.

import java.util.HashMap;
import java.util.Map;

Map hashMap = new HashMap();
hashMap.put("biz", "type:web");
searchParams.setCustomParam(hashMap);

Configure the re-search feature

Use the re-search feature to automatically rerun a query when the initial result count falls below a threshold.

// strategy:threshold,params:total_hits#10 — if total_hits on the first run is less than 10,
// the query is automatically rerun.
// Map<String, String> reSearchParams = new HashMap<String, String>();
// reSearchParams.put("re_search", "strategy:threshold,params:total_hits#10");
// Specify the from_request_id of the associated query.
// reSearchParams.put("from_request_id", "159851481919726888064081");
// searchParams.setCustomParam(reSearchParams);

// To disable the re-search feature:
// searchParams.putToCustomParam("disable", "re_search");

Execute the query and handle results

Submit the query and parse the JSON response. Check the error code and message if a request fails — do not rely on HTTP status alone.

import com.aliyun.opensearch.sdk.dependencies.org.json.JSONObject;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchClientException;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchException;
import com.aliyun.opensearch.search.SearchResultDebug;
import com.aliyun.opensearch.sdk.generated.search.general.SearchResult;

try {
    // Run the query
    SearchResult searchResult = searcherClient.execute(paramsBuilder);
    String result = searchResult.getResult();

    // Parse and print the response
    JSONObject obj = new JSONObject(result);
    System.out.println(obj.toString());

    // Print the request URL for debugging
    SearchResultDebug debugResult = searcherClient.executeDebug(searchParams);
    System.out.println(debugResult.getRequestUrl());

} catch (OpenSearchException e) {
    e.printStackTrace();
} catch (OpenSearchClientException e) {
    e.printStackTrace();
}

What's next