Write a sorting script in Cava

更新时间:
复制 MD 格式

Cava sort scripts give you full control over document scoring during the fine sort phase. Unlike sort expressions, Cava lets you implement arbitrary business logic — combining document fields, text relevance signals, and custom parameters into a single score.

Cava sort scripts apply only to the fine sort phase. For rough sort configuration, see the rank parameter reference.

For information about how to create and manage sort scripts via the API, see API operations for Cava management. You can also create sort scripts by using the command-line tool provided by OpenSearch.

How it works

For each search request, OpenSearch runs your Cava script in two stages:

  1. `init` — called once per request to initialize shared state: member variables, attribute field declarations, and scoring features.

  2. `score` — called once per document in the fine sort to compute that document's score. The return value determines the document's rank.

If init fails, OpenSearch returns an error and terminates the request. If score raises an error or the request exceeds resource limits, OpenSearch reports an error but returns partial results.

Write a sort script

All sort scripts must implement the BasicSimilarityScorer class in the users.scorer package. The class name and package name are fixed — changing either causes a compilation error.

package users.scorer;
import com.aliyun.opensearch.cava.framework.OpsScoreParams;
import com.aliyun.opensearch.cava.framework.OpsScorerInitParams;

class BasicSimilarityScorer {
    // Declare member variables here (scoring features, custom parameters)

    boolean init(OpsScorerInitParams params) {
        // Initialize member variables and declare attribute fields
        return true;
    }

    double score(OpsScoreParams params) {
        double score = 0;
        // Compute and return the document score
        return score;
    }
}

init method

PropertyDetail
ParameterOpsScorerInitParams — provides access to search request information
CalledOnce per search request
Return valueboolean — return false to abort the request
Use forDeclaring attribute fields, initializing scoring features, reading request parameters from kvpairs

The init method signature is fixed. Do not change the parameter type or return type.

score method

PropertyDetail
ParameterOpsScoreParams — provides access to both request and document information
CalledOnce per document in the fine sort
Return valuedouble — the document's score; higher scores rank higher
Use forReading attribute field values, computing the final score

The score method signature is fixed. Do not change the parameter type or return type.

Important

Do not read search request information (such as kvpairs parameters or scoring feature objects) inside score. Read them in init and store them as member variables. Reading request-level data on every document call wastes significant performance.

Import system libraries

Use explicit import statements to reference OpenSearch feature libraries. The wildcard syntax import com.aliyun.opensearch.cava.framework.*; is not supported.

Example

The following script combines text relevance with a document field (shop_margin) to produce a custom score.

package users.scorer;
import cava.lang.CString;
import com.aliyun.opensearch.cava.framework.OpsScoreParams;
import com.aliyun.opensearch.cava.framework.OpsScorerInitParams;
import com.aliyun.opensearch.cava.framework.OpsRequest;
import com.aliyun.opensearch.cava.framework.OpsKvPairs;
import com.aliyun.opensearch.cava.framework.OpsDoc;
import com.aliyun.opensearch.cava.features.similarity.TextRelevance;

class BasicSimilarityScorer {
    TextRelevance _textRelevance; // Declare the scoring feature as a member variable

    boolean init(OpsScorerInitParams params) {
        // Declare attribute fields used in score calculation
        if (!params.getDoc().requireAttribute("shop_margin")) {
            return false;
        }
        // Initialize the scoring feature once per request
        _textRelevance = TextRelevance.create(params, "default", "name");
        return true;
    }

    double score(OpsScoreParams params) {
        float shopMargin = params.getDoc().docFieldFloat("shop_margin"); // Read the attribute field
        float textScore = _textRelevance.evaluate(params);              // Evaluate the pre-initialized feature
        return textScore * 30.0 + shopMargin;
    }
}

Key patterns in this example:

  • _textRelevance is initialized once in init and reused across all score calls — avoiding repeated initialization overhead.

  • shop_margin is declared with requireAttribute in init before being read in score. All attribute fields must be declared this way.

  • Request-level data (_textRelevance) is read in init; document-level data (shopMargin) is read in score.

Constraints and performance guidelines

Package and class constraints:

  • Define all classes in the users.scorer package. Only single-file uploads are supported, so you cannot split code across packages.

  • Do not modify the BasicSimilarityScorer class name, package name, or the signatures of init and score.

Performance patterns:

  • Define scoring features as member variables and initialize them in init. Initializing features inside score causes significant performance overhead because score runs once per document.

  • Define custom request parameters as member variables and read them in init, not score.

Attribute fields:

  • Any document field accessed in score must be defined as an attribute field in the application schema and declared with requireAttribute in init.

Memory limit:

The maximum memory per search request is 40 MB. If exceeded, OpenSearch reports an error and returns partial results — only some documents are scored. To stay within the limit:

  • Avoid frequent new statements inside score.

  • Avoid working with large strings inside score.

  • Use the rerank_size parameter to reduce the number of documents sent to fine sort.

Loop and invocation limit:

The maximum number of for loop iterations and function invocations per request is 100,000. If exceeded, OpenSearch reports an error and returns results early. Adjust rerank_size to reduce the document count if you approach this limit.

What's next