# es-search

Part of **ES**

# Elasticsearch Search

## Capabilities Overview

| Sub-capability | Calling Mode | Description |
|----------------|--------------|-------------|
| Perform Search | Synchronous | Execute basic search queries against Elasticsearch indexes. |
| Scroll Search | Synchronous | Perform scroll-based searches to retrieve large result sets in batches. |
| Paginate Search Results | Synchronous | Configure pagination settings for search result retrieval. |
| Configure Search Pagination and Response Format | Synchronous | Set up search configuration including pagination and response formatting options. |
| Filter Search Results | Synchronous | Apply filters to narrow down search results based on specific criteria. |
| Sort Search Results | Synchronous | Configure sorting parameters for search result ordering. |
| Calculate Document Statistics | Synchronous | Perform aggregation operations to calculate statistics on document fields. |
| Configure Search Result Summary | Synchronous | Set up summary generation for search results including highlighting. |
| Get Suggestions | Synchronous | Retrieve search suggestions based on partial input queries. |
| Pass Field Values to Sort Expression | Synchronous | Use key-value pairs to pass field values into sort expressions. |
| Execute Parameterized Query | Synchronous | Run queries with dynamic parameters for flexible search execution. |
| Perform Search Operations | Synchronous | Execute searches with various clauses like filter, sort, aggregate, and distinct. |
| Configure Search Parameters | Synchronous | Set up search parameters using builders and config classes. |
| Handle Search Results | Synchronous | Process and debug search results, including getting result details and request URLs. |
| Push and Search Documents | Synchronous | Push documents to the index and perform knowledge-based or Q&A searches. |
| Query Index | Synchronous | Perform searches against Elasticsearch indexes. |
| Manage Second Rank | Synchronous | Configure fine-sort expressions for search result ranking. |
| Manage Intervention Dictionary | Synchronous | Create and maintain dictionaries for query understanding and entity resolution. |
| Manage Sort Expression | Synchronous | List and manage sort expressions for search results. |
| Manage Rough Sort | Synchronous | Create, describe, list, modify, and remove rough sort expressions. |
| Manage Sort Script | Synchronous | Create, delete, update, and retrieve sort scripts and their files. |
| Update Summary Settings | Synchronous | Update summary settings for search results. |
| Manage Query Processor | Synchronous | Describe, list, modify, and remove query processors for search analysis. |
| Test Query Analysis | Synchronous | Analyze query processor results and NER entity settings. |
| List Query Result | Synchronous | Retrieve results from Elasticsearch queries. |
| Release Sort Script | Synchronous | Release sort scripts for use in the search engine. |
| Get Search Test Results | Synchronous | Retrieve results from search tests. |
| List REST Query Results | Synchronous | Retrieve results from REST-based search queries. |
| Get Domain Info | Synchronous | Retrieve domain information for search services. |
| Create A/B Test Experiment | Synchronous | Create A/B test experiments for search analysis. |

## API Calling Patterns

### Authentication
The primary authentication method is Bearer Token authentication using an API key.

- Header format: `Authorization: Bearer <your_api_key>`
- Environment variable: `DASHSCOPE_API_KEY`
- Alternative methods exist (like AccessKey/Secret), but Bearer Token is recommended for most use cases.

### Service Endpoint
The base URL pattern varies by region and service type:

- China regions: `https://opensearch.cn-hangzhou.aliyuncs.com`
- International regions: `https://opensearch.cn-shanghai.aliyuncs.com`

Common regions include:
- cn-hangzhou
- cn-shanghai  
- cn-shanghai

### Basic Search Pattern
For standard search operations:

1. Construct a query with required parameters (`query`, `index`)
2. Add optional clauses (`filter`, `sort`, `aggregate`, etc.)
3. Send a POST request to the search endpoint
4. Parse the JSON response containing hits, aggregations, and metadata

Key headers:
- `Authorization: Bearer $DASHSCOPE_API_KEY`
- `Content-Type: application/json`

### Scroll Search Pattern
For retrieving large result sets:

1. **Initial Request**: Send a search request with `scroll` parameter (e.g., "1m") and `search_type=scan`
2. **Receive Response**: Extract the `scroll_id` from the response
3. **Subsequent Requests**: Send requests with the `scroll_id` to fetch next batches
4. **Continue**: Repeat step 3 until no more results are returned
5. **Cleanup**: Scroll context expires automatically after the specified duration

Each scroll request counts as a separate billable request.

### Knowledge Search Pattern
For Q&A and knowledge-based searches:

1. Push documents to the knowledge base using the `knowledge-bulk` endpoint
2. Send search queries to the `knowledge-search` endpoint with question text
3. Parse results containing relevant document snippets and scores

Documents can be structured (JSON fields) or unstructured (base64-encoded files).

### Management API Pattern
For managing search configuration (sort expressions, dictionaries, etc.):

1. Identify the resource type (second-rank, intervention-dictionary, query-processor, etc.)
2. Use appropriate HTTP method (POST for create, GET for read, PUT for update, DELETE for remove)
3. Include required path parameters (appGroupIdentity, appId, name)
4. Provide request body for create/update operations
5. Parse response containing resource details and metadata

## Parameter Reference

### Perform Search

| Parameter | Type | Required | Default | Constraints | Description |
|-----------|------|----------|---------|-------------|-------------|
| index | String | true | - | - | The index field to search. Configured when you define the index schema. |
| search query | String | true | - | - | The term or phrase to search for. Enclose in single quotation marks ('') or double quotation marks (""). |
| boost | INT | false | 99 | 0–99 | Relevance weight for the query condition. Valid values: 0–99. Default: 99. Values below 0 are treated as 0; values above 99 are treated as 99. Takes effect only when exact_match_boost() is configured in a rough sort expression. |

### Scroll Search

| Parameter | Type | Required | Default | Constraints | Description |
|-----------|------|----------|---------|-------------|-------------|
| scroll | STRING | true | - | Valid units: w, d, h, m, s; e.g., 1m, 2h, 3d | The validity period of the scroll ID, specified as a number followed by a unit: weeks (w), days (d), hours (h), minutes (m), or seconds (s). Example: 1m. Required for the first request only. |
| search_type | STRING | true | - | Must be 'scan' | The scroll search type. Set to scan. Required only for the first request. |
| scroll_id | STRING | true | - | - | The scroll ID returned by the previous response. Not required for the first request. |
| fetch_fields | STRING | false | - | - | The fields to return in search results. |

### Paginate Search Results

| Parameter | Type | Required | Default | Constraints | Description |
|-----------|------|----------|---------|-------------|-------------|
| start | int | false | 0 | [0, 5000] | Specifies the offset of the first document to return. |
| hit | int | false | 10 | [0, 500] | Specifies the maximum number of documents to return. |
| format | string | false | json | - | Specifies the format of the returned documents. The fulljson format includes extra nodes that are not in the json format, such as variableValue and sortExprValues. |
| rerank_size | int | false | 200 | [0, 2000] | You can specify the number of documents to retrieve from a single list for fine-grained ranking. |
| total_rank_size | int | false | - | - | Sets the number of documents that participate in coarse sorting. |
| default_operator | string | false | AND | 'AND' or 'OR' | Specifies the default query operator for the current query. This parameter is supported only for dedicated instances. |

### Filter Search Results

| Parameter | Type | Required | Default | Constraints | Description |
|-----------|------|----------|---------|-------------|-------------|
| query | string | true | - | - | The main search query string. |
| filter | string | false | - | Must be a valid expression using supported operators and functions | A condition used to further filter documents after the query phase. |

### Sort Search Results

| Parameter | Type | Required | Default | Constraints | Description |
|-----------|------|----------|---------|-------------|-------------|
| sort | string | false | Descending by RANK if not specified | Format: +field1;-field2;... or use functions like distance(), tag_match(). Fields must be defined in schema. | Specifies the field(s) and order for sorting query results. |

### Calculate Document Statistics

| Parameter | Type | Required | Default | Constraints | Description |
|-----------|------|----------|---------|-------------|-------------|
| group_key:field | field: an attribute field | true | - | Fields of the INT, LITERAL, INT_ARRAY, or LITERAL_ARRAY type. If the attribute field is of the INT_ARRAY or LITERAL_ARRAY type and an item in the array is repeated, the number of its occurrences is counted. | Specifies the name of the field for which you want to collect statistics. You must configure an attribute field in this parameter. |
| agg_fun | - | true | - | The built-in functions: count(id), sum(id), max(id), min(id), and distinct_count (id). | You can set func to the count(), sum(id), max(id), min(id), or distinct_count(id) built-in function to calculate the number of documents, the sum of field values, the maximum field value, the minimum field value, or the number of unique values in a field. You can use multiple functions at a time by separating them with number signs (#). You can reference multiple fields in the sum(), max(), or min() function by using basic arithmetic operators. |
| range | - | false | - | The values between Number 1 and Number 2 and values greater than Number 2. Values of fields of the STRING type cannot be aggregated to collect statistics. | Generates statistics based on value ranges. This parameter can be used for data distribution. You can specify only one range parameter in the aggregate clause. |
| agg_filter | - | false | - | - | Retrieves documents that meet the specified conditions. |
| agg_sampler_threshold | INT | false | - | - | Specifies the threshold for document sampling. The retrieved documents whose ranks are higher than the threshold are counted in sequence in statistics, whereas those whose ranks are lower than the threshold are sampled based on the value of the agg_sampler_step parameter. |
| agg_sampler_step | INT | false | - | - | Specifies the sampling step size. The value indicates the intervals at which the documents whose ranks are lower than the threshold specified by the agg_sampler_threshold parameter are sampled. Statistics that are collected by the sum() and count() functions are processed in the following way: The system multiplies the statistics of documents whose ranks are lower than the threshold by the sampling step size to generate the estimated statistics. Then, the system adds the estimated statistics to the statistics of documents whose ranks are higher than the threshold to generate the final statistics. |
| max_group | INT | false | 1000 | - | Specifies the maximum number of key-items pairs that can be returned. |

## Code Examples

### Basic Search Query - bash - all

```bash
query=title:'Peking University'
```

### Scroll Search Implementation - java - all

```java
package com.aliyun.opensearch;

import com.aliyun.opensearch.OpenSearchClient;
import com.aliyun.opensearch.SearcherClient;
import com.aliyun.opensearch.sdk.dependencies.com.google.common.collect.Lists;
import com.aliyun.opensearch.sdk.dependencies.org.json.JSONObject;
import com.aliyun.opensearch.sdk.generated.OpenSearch;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchClientException;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchException;
import com.aliyun.opensearch.sdk.generated.search.*;
import com.aliyun.opensearch.sdk.generated.search.general.SearchResult;
import com.aliyun.opensearch.search.SearchParamsBuilder;

import java.nio.charset.Charset;

public class testScroll {

    // Scroll queries do not support the aggregate, distinct, or rank clause,
    // but do support sorting by a single field.
    private static String appName = "The name of the OpenSearch application for which you want to implement scroll queries";
    private static String host = "The endpoint of the OpenSearch API in your region";

    public static void main(String[] args) {
        // Read credentials from environment variables.
        // Configure the environment variables before running this code.
        String accesskey = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        String secret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");

        // Print the default encoding format.
        System.out.println(String.format("file.encoding: %s", System.getProperty("file.encoding")));
        System.out.println(String.format("defaultCharset: %s", Charset.defaultCharset().name()));

        // Create an OpenSearch object.
        OpenSearch openSearch = new OpenSearch(accesskey, secret, host);

        // Create an OpenSearchClient object.
        OpenSearchClient serviceClient = new OpenSearchClient(openSearch);

        // Create a SearcherClient object.
        SearcherClient searcherClient = new SearcherClient(serviceClient);

        // Configure the config clause: paging settings, data format, and application name.
        Config config = new Config(Lists.newArrayList(appName));

        // The start parameter has no effect on scroll queries. The offset is always 0.
        config.setStart(0);
        // Return 5 documents per batch.
        config.setHits(5);

        // Set the data format to FULLJSON. Supported formats: JSON, FULLJSON.
        config.setSearchFormat(SearchFormat.FULLJSON);

        // Specify the fields to return.
        config.setFetchFields(Lists.newArrayList("id", "name", "phone", "int_arr", "literal_arr", "float_arr", "cate_id"));
        // Note: Set rerank_size using the setReRankSize method of the Rank class.

        // Create a SearchParams object and set the search query.
        SearchParams searchParams = new SearchParams(config);

        // To query multiple index fields, specify all fields in a single setQuery call.
        // Separate setQuery calls overwrite each other.
        searchParams.setQuery("name:'opensearch'");

        // (Optional) Set a filter condition.
        // searchParams.setFilter("cate_id<=3");

        // Create a DeepPaging object to enable scroll queries.
        DeepPaging deep = new DeepPaging();
        // Specify a validity period for the scroll ID to be used by the next scroll query, in minutes.
        // Default value: 1m. In this example, the value is set to 3m.
        deep.setScrollExpire("3m");

        // Attach the DeepPaging object to the search parameters.
        searchParams.setDeepPaging(deep);

        // Create a SearchParamsBuilder for easier parameter configuration.
        SearchParamsBuilder paramsBuilder = SearchParamsBuilder.create(searchParams);

        // Run the scroll queries.
        // This example assumes 25 matching documents with 5 documents per batch,
        // so 5 batches return results and the 6th batch is empty.
        SearchResult searchResult;
        try {
            searchResult = searcherClient.execute(paramsBuilder);
            String result = searchResult.getResult();
            JSONObject obj = new JSONObject(result);

            for (int i = 1; i <= 6; i++) {
                // When you run the first scroll query, a scroll ID is returned.
                // To obtain document data, use this scroll ID to run the scroll query again.
                deep.setScrollId(new JSONObject(obj.get("result").toString()).get("scroll_id").toString());
                // Specify a validity period for the scroll ID to be used by the next scroll query, in minutes.
                // Default value: 1m. In this example, the value is set to 3m.
                // If you do not want to use the default value, you must set a validity period each time before you run a scroll query.
                deep.setScrollExpire("3m");

                searchResult = searcherClient.execute(paramsBuilder);
                result = searchResult.getResult();
                obj = new JSONObject(result);

                System.out.println("Results for Query No." + i + ": " + obj.get("result"));

                // Sleep for 1 second to avoid exceeding the queries per second (QPS) limit.
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

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

### Knowledge Search - php - all

```php
<?php
require_once($path . "/OpenSearch/Autoloader/Autoloader.php");

use OpenSearch\Client\OpenSearchClient;

// Specify your AccessKey pair.
// Obtain the AccessKey ID and AccessKey secret from environment variables. 
// Configure environment variables before you run the sample code. For more information, see the "Configure environment variables" section in this topic.
// Specify the AccessKey ID of your Alibaba Cloud account.
$accessKeyId = getenv('ALIBABA_CLOUD_ACCESS_KEY_ID');
// Specify the AccessKey secret of your Alibaba Cloud account.
$secret = getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET');
$end Point = '<The endpoint of the OpenSearch API in your region>';
$appName = '<The application name>';
$options = array('debug' => true);
$requestBody = "{\"question\":{\"text\":\"Based on the survey of various types of typical sites\",\"type\":\"TEXT\"}}";

$client = new OpenSearchClient($accessKeyId, $secret, $end Point, $options);

$uri = "/apps/{$appName}/actions/knowledge-search";

try{
    $ret = $client->post($uri, $requestBody);
    print_r(json_decode($ret->result, true));
}catch (\Throwable $e) {
    print_r($e);
}
```

### Q&A Test Feature - python - all

```python
# -*- coding: utf-8 -*-

import time, os
from typing import Dict, Any

from Tea.exceptions import TeaException
from Tea.request import TeaRequest
from alibabacloud_tea_util import models as util_models
from BaseRequest import Config, Client

class LLMSearch:
    def __init__(self, config: Config):
        self.Clients = Client(config=config)
        self.runtime = util_models.RuntimeOptions(
            connect_timeout=10000,
            read_timeout=10000,
            autoretry=False,
            ignore_ssl=False,
            max_idle_conns=50,
            max_attempts=3
        )
        self.header = {}

    def searchDoc(self, app_name: str, body: Dict, query_params: dict={}) -> Dict[str, Any]:
        try:
            response = self.Clients._request(method="POST", pathname=f'/v3/openapi/apps/{app_name}/actions/knowledge-search',
                                             query=query_params, headers=self.header, body=body, runtime=self.runtime)
            return response
        except TeaException as e:
            print(e)

if __name__ == "__main__":
    # Specify the endpoint. The value does not contain the http:// prefix.
    endpoint = "<endpoint>"

    # Specify the request protocol. Valid values: HTTPS and HTTP.
    endpoint_protocol = "HTTP"

    # Specify your AccessKey pair
    # Reads the AccessKey ID and AccessKey Secret from environment variables
    # You must first set the environment variables. For more information, see the "Configure environment variables" section of this topic
    access_key_id = os.environ.get("ALIBABA_CLOUD_ACCESS_KEY_ID")
    access_key_secret = os.environ.get("ALIBABA_CLOUD_ACCESS_KEY_SECRET")

    # Specify the authentication method. Default value: access_key. A value of sts indicates authentication based on Resource Access Management (RAM) and Security Token Service (STS).
    # Valid values: sts and access_key. This example uses access_key
    # auth_type = "access_key"
    # If you are not using an RAM user, omit the type and security_token parameters
    # Specify common request parameters
    # Configs = Config(endpoint=endpoint, access_key_id=access_key_id, access_key_secret=access_key_secret,
    #                  type=auth_type, protocol=endpoint_protocol)

    # If you use authentication based on RAM and STS, you must specify the security_token parameter. You can call the AssumeRole operation of Alibaba Cloud RAM to obtain an STS token
    auth_type = "sts"
    security_token =  "<security_token>"

    # Specify common request parameters
     Configs = Config(endpoint=endpoint, access_key_id=access_key_id, access_key_secret=access_key_secret,
                      security_token=security_token, type=auth_type, protocol=endpoint_protocol)

    # Create an OpenSearch instance
    ops = LLMSearch(Configs)
    app_name = "Replace with your application ID"

    # --------------- Document search ---------------

    docQuery = {"question": {"text": "search", "type": "TEXT"}}

    res1 = ops.searchDoc(app_name=app_name, body=docQuery)
    print(res1)
```

### Create Fine Sort Expression - curl - all

```bash
curl -X POST 'https://opensearch.cn-hangzhou.aliyuncs.com/v4/openapi/app-groups/my_app_group_name/apps/110157886/second-ranks' \
-H 'Authorization: Bearer $DASHSCOPE_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"name":"test","meta":"random()","description":"my_test","active":true}'
```

### Create Intervention Dictionary - curl - all

```bash
curl -X POST https://api.aliyun.com/v4/openapi/intervention-dictionaries \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
  "dryRun": false,
  "body": {
    "name": "ner_dict_ec",
    "type": "ner",
    "analyzerType": "SYSTEM"
  }
}'
```

### Push Unstructured Documents - python - all

```python
# -*- coding: utf-8 -*-

import time, os
import base64
from Tea.exceptions import TeaException
from Tea.request import TeaRequest
from alibabacloud_tea_util import models as util_models
from opensearch.V3_cases.doc_search.BaseRequest111 import Config, Client

class knowledge:
    def __init__(self, config: Config):
        self.Clients = Client(config=config)
        self.runtime = util_models.RuntimeOptions(
            connect_timeout=10000,
            read_timeout=10000,
            autoretry=False,
            ignore_ssl=False,
            max_idle_conns=50,
            max_attempts=3
        )
        self.header = {}

    def docBulk(self, app_name: str,doc_content: list):
        try:
            response = self.Clients._request(method="POST",
                                             pathname=f'/v3/openapi/apps/{app_name}/actions/knowledge-bulk',
                                             query={}, headers=self.header,
                                             body=doc_content, runtime=self.runtime)
            return response
        except Exception as e:
            print(e)

if __name__ == "__main__":
    # Specify the endpoint of the OpenSearch API. The value does not contain the http:// prefix.
    endpoint = "<endpoint>"
    # Specify the request protocol. Valid values: HTTPS and HTTP.
    endpoint_protocol = "HTTP"
    # Specify your AccessKey pair.
    # Obtain the AccessKey ID and AccessKey secret from environment variables. 
    # You must configure environment variables before you run this code. For more information, see the "Configure environment variables" section of this topic.
    access_key_id = os.environ.get("ALIBABA_CLOUD_ACCESS_KEY_ID")
    access_key_secret = os.environ.get("ALIBABA_CLOUD_ACCESS_KEY_SECRET")
    # Specify the authentication method. Default value: access_key. A value of sts specifies authentication based on Resource Access Management (RAM) and Security Token Service (STS).
    # Valid values: sts and access_key.
    auth_type = "access_key"
    # If you use authentication based on RAM and STS, you must specify the security_token parameter. You can call the AssumeRole operation of Alibaba Cloud RAM to obtain an STS token.
    security_token = "<security_token>"
    # Specify common request parameters.
    # Note: The security_token and type parameters are required only if you use the SDK as a RAM user.
    Configs = Config(endpoint=endpoint, access_key_id=access_key_id, access_key_secret=access_key_secret,
                     security_token=security_token, type=auth_type, protocol=endpoint_protocol)
    # Create an OpenSearch LLM-Based Conversational Search Edition instance.
    ops = knowledge(Configs)
    app_name = "The name of the OpenSearch LLM-Based Conversational Search Edition instance"

    # ---------------Push unstructured documents to an OpenSearch LLM-Based Conversational Search Edition instance---------------
    # Modify the paths of local files.
    with open('/Users/liu/Downloads/test.docx', 'rb') as file:
        data = file.read()
        data_b64 = base64.b64encode(data)

        document = [
        {
            "fields": {
                "id": "1",
                "title": "test.pdf",
                "url": "www.baidu.com",
                "content": data_b64,
                "category": "opensearch",
                "timestamp": 1691722088645,
                "score": 0.8821945219723084
            },
            "cmd": "BASE64"
        }
    ]

        # Delete documents.
        deletedocument = {"cmd": "DELETE", "fields": {"id": 2}}
        documents = document
        res5 = ops.docBulk(app_name=app_name, doc_content=documents)
        print(res5)
```

### Filter and Sort Query - javascript - all

```javascript
query=default:'Zhejiang University'&&filter=category=2&&sort=+type;-RANK
```

## Response Format

```json
{
    "status": "OK",
    "request_id": "150150574119953661605242",
    "result": {
        "searchtime": 0.005029,
        "total": 1,
        "num": 0,
        "viewtotal": 1,
        "scroll_id": "eJxtUMtuhDAM/BrvOYQC5cABdulvRFFIirsm2TpBavv1Ndut1EMlS36NZ0Y2ZHMxbueceAjIuWCMnrPjRITLyfzZm83y9V QVGT8x80U3PxQNUqieVZV1/an4ItbTUBPSx5wgXqKdvOSbmuKR8ZYjGWWirB4tvToAiX7u3G2eCNK77vnz8GlGPAV6suKBeqxAn0OiTd7NGEnesspyoyFLF6hecn4JUKjVgp0K3FnkfMfIyPoDuYWegX9GeYOpicY9TG8gwOSuBL04X1 MMg3ROwCesLlG6X7a2o=",
        "items": [],
        "facet": []
    },
    "errors": [],
    "tracer": ""
}
```

**Key Fields**:
- `status` — Overall request status (OK or error)
- `request_id` — Unique identifier for the request for debugging
- `result.scroll_id` — Scroll ID for subsequent batch requests
- `result.items` — Array of matched documents
- `result.total` — Total number of matching documents
- `result.num` — Number of documents in current batch
- `result.facet` — Aggregation results when using aggregate clause
- `errors` — Array of any errors encountered during processing

## Error Handling

| Error Code (Code) | Description (Description) | Recommended Action (Recommended Action) |
|-------------------|---------------------------|----------------------------------------|
| 400 | Bad Request – The query clause is missing, malformed, or contains invalid syntax (e.g., unmatched quotes). | Validate query syntax, ensure proper quoting of search terms, and check for missing required parameters. |
| 404 | Not Found – The specified index field does not exist or is not searchable. | Verify that the index field exists in your application schema and is configured as searchable. |
| Scroll_id is expired | The scroll ID expired before the next batch was fetched. Modify the scroll parameter and restart the scroll session from step 1. | Increase the scroll duration parameter or fetch batches more quickly. Restart the scroll session from the beginning. |
| Invalid scroll_id | The value of the scroll_id parameter in a request is invalid. | Ensure you're using the exact scroll_id returned from the previous response without modification. |
| 6135 | Constant expression type error. Occurs when values for LITERAL type fields are not enclosed in double quotation marks. | Enclose LITERAL field values in double quotes in your filter expressions. |
| 401 | Unauthorized – Invalid or missing authentication credentials. | Verify your API key or AccessKey credentials and ensure they're properly configured in environment variables. |
| 403 | Forbidden – The RAM user does not have sufficient permissions to perform the operation. | Check your RAM user permissions and ensure they have the required OpenSearch policies attached. |
| 429 | Too Many Requests – Exceeded the QPS limit. Implement backoff or reduce request frequency. | Implement exponential backoff with delays between requests, or contact support to increase your QPS limit. |

### Rate Limits & Retry
- Standard applications: 100 QPS per application
- Each scroll batch counts as one request
- Knowledge search: 100 QPS per AccessKey
- Implement 1-second delay between requests when approaching limits
- For 429 errors, use exponential backoff starting with 1-second delay

## Environment Requirements

- OpenSearch SDK for Java V3.1 or later (for Java examples)
- open-search-php-client>=1.0.0 (for PHP examples)  
- alibabacloud_tea_util>=0.3.0, alibabacloud_opensearch_util>=1.0.0, alibabacloud_credentials>=0.2.0 (for Python examples)
- Environment variables: `ALIBABA_CLOUD_ACCESS_KEY_ID`, `ALIBABA_CLOUD_ACCESS_KEY_SECRET`, or `DASHSCOPE_API_KEY`

## FAQ

Q: How do I handle pagination for more than 5,000 results?
A: Use scroll search instead of standard pagination. The sum of start and hit parameters cannot exceed 5,000 in regular searches, but scroll search allows you to retrieve unlimited results in batches.

Q: What's the difference between rough sort (first-rank) and fine sort (second-rank)?
A: Rough sort (first-rank) performs initial document scoring and filtering using simple expressions like BM25, while fine sort (second-rank) applies more complex ranking logic to the top results from rough sort for final ordering.

Q: How do I authenticate my API requests?
A: Use Bearer Token authentication with your API key in the Authorization header: `Authorization: Bearer $DASHSCOPE_API_KEY`. Set your API key in the `DASHSCOPE_API_KEY` environment variable.

Q: Can I search across multiple index fields simultaneously?
A: Yes, you can search multiple fields by including them in a single query clause using logical operators, like: `query=(title:'search term' OR content:'search term')`.

Q: What happens when my scroll ID expires?
A: When a scroll ID expires, you'll receive an error. You must restart the scroll session from the beginning with a new initial request. Consider increasing the scroll duration (e.g., from "1m" to "5m") if you need more time between batches.

## Pricing & Billing

### Billing Model
Billing is per-request for all search and management operations. Each API call counts as one request, including scroll batches, document pushes, and configuration changes.

### Price Reference

| Tier/Model | Input Price | Output Price | Other Fees |
|------------|-------------|--------------|------------|
| standard | 0.0001 / | 0.0001 / | - |
| standard | 0.0001 / | 0.0002 / | - |
| default | 0.001 / | 0.002 / | - |

### Free Tier
- Monthly 10,000 free queries for basic search
- 500 free requests/month for new users (scroll queries)
- Monthly 1,000 free requests for knowledge search and document operations

### Usage Limits
- Single query supports maximum 8K tokens
- Scroll batches can contain at most 500 documents
- Single document push can submit up to 1000 documents
- Unstructured document uploads limited to 10MB per file

### Billing Notes
- Requests are billed per execution regardless of success or failure
- Async operations are billed upon completion
- Minimum charge is 1 request per API call
- Dry runs for validation are also billed