TagMatch

更新时间:
复制 MD 格式

TagMatch matches per-user tag preferences (passed in a kvpairs clause) against per-document tag fields, then combines the resulting per-key scores into a final ranking weight. Use it in sort scripts to boost documents whose tags align with a user's interests.

How it works

Each search request carries a kvpairs clause that encodes the user's tag preferences as key-value pairs. TagMatch compares those keys against the document's tag field, computes a score for every matched key using kvOperatorName (or a constant kvResult), and then merges all per-key scores into a single value using mergeOperatorName. That value is added to the document's final sort score.

Use cases

Weighted tag matching

A forum assigns numeric IDs to content tags: funny = 1, sports = 5, news = 3, music = 6. Each post stores the IDs and their weights as a float array — for example, a post tagged funny (0.5), sports (0.5), and news (0.1) has a tag field value of [1 0.5 5 0.5 3 0.1].

After analyzing each member's reading history, you know their tag preferences. The member nba_fans favors sports (weight 0.6) and funny (weight 0.3). Pass those preferences in the kvpairs clause when they search: kvpairs=user_tag:5=0.6:1=0.3.

In your sort script, call TagMatch("user_tag", "tag", "mul", "sum", false, true, 50):

  • kvOperatorName = mul: multiply the query-side weight by the document-side weight for each matched tag.

  • mergeOperatorName = sum: add the per-tag scores together.

When nba_fans finds that post, both sports and funny match:

  • Sports score: 0.5 × 0.6 = 0.3

  • Funny score: 0.5 × 0.3 = 0.15

  • Final TagMatch score: 0.3 + 0.15 = 0.45

That 0.45 is added to the document's overall sort score, surfacing the post higher for this user.

Key-only tag matching (no weights)

Clothing items carry attribute tags without weights: 1 = young, 2 = middle-aged, 3 = fresh, 4 = fashion, 5 = women, 6 = men. Items store the tag IDs in an options field as a key-only array — for example, [1 4 5] for a young, fashion, women item.

A user's historical purchases reveal she is young and female. When she searches, add kvpairs=user_options:1:3:5 to the request.

In your sort script, call TagMatch("user_options", "options", 10F, "sum", false, false):

  • kvResult = 10: each matched tag contributes a fixed score of 10.

  • mergeOperatorName = sum: add all per-tag scores.

  • fieldIsKv = false: the document field contains keys only, not key-value pairs.

Both young and women match → 10 + 10 = 20.

Prerequisites

Before you begin, ensure that you have:

  • An OpenSearch application with the Industry Algorithm Edition

  • A sort script that follows the CAVA init / score pattern

  • A kvpairs clause in your search request that carries the user's tag data

Create a TagMatch object

All TagMatch objects are created by calling TagMatch.create() in the init method of your scorer class. Call _tagMatch.evaluate(params) in the score method to compute and return the score.

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

class BasicSimilarityScorer {
    TagMatch _tagMatch;

    boolean init(OpsScorerInitParams params) {
        // Replace the arguments below with your field names and operators.
        _tagMatch = TagMatch.create(params, "user_tag", "tag", "mul", "sum", false, true, 50);
        return true;
    }

    double score(OpsScoreParams params) {
        return _tagMatch.evaluate(params);
    }
}

Parameters

create() with kvOperatorName (string operator)

Use this overload when you want to compute a per-key score by combining the query-side and document-side values with an operator (for example, mul to multiply them).

ParameterTypeRequiredDefaultDescription
paramsOpsScorerInitParamsYesScore calculation parameters. See OpsScoreParams.
queryKeyCStringYesName of the field in the kvpairs clause that carries the user's tags. Keys and values are separated by =; pairs are separated by :. Example: kvpairs=query_tags:10=0.67:960=0.85:1=48. To pass keys only (no values), omit the =value part: kvpairs=cats:10:960:1.
fieldNameCStringYesName of the attribute field in documents that stores tags. Must be an integer or float array. Odd positions hold keys; even positions hold values: key0 value0 key1 value1. If the array is a float array, key values are converted to 64-bit integers during matching.
kvOperatorNameCStringYesOperation applied to the query-side and document-side values for each matched key. Valid values: max (greater value), min (smaller value), avg (average), mul (product), query_value (use the query-side value), doc_value (use the document-side value).
mergeOperatorNameCStringYesOperation applied to all per-key scores to produce the final TagMatch score. Valid values: max, min, sum, avg, first_match (use the score of the first matched key only).
hasDefaultValuebooleanNofalseIf true, the first key-value pair in fieldName is used as the default score. The field format becomes default_score k0 v0 k1 v1. If false, there is no default.
fieldIsKvbooleanNotrueIf true, the document field contains key-value pairs. If false, the document field contains keys only (no per-document weights).
maxKvCountintNo50Maximum number of key-value pairs from the queryKey field to match. Cannot exceed 5120.

create() with kvResult (constant score)

Use this overload when every matched key should contribute the same fixed score, regardless of the values in either field — for example, when your document field contains keys only.

This overload takes the same parameters as the kvOperatorName overload, with one difference:

ParameterTypeRequiredDefaultDescription
kvResultdoubleYesFixed score returned for each matched key, replacing kvOperatorName.

All other parameters (params, queryKey, fieldName, mergeOperatorName, hasDefaultValue, fieldIsKv, maxKvCount) behave identically to the kvOperatorName overload.

Overload reference

Both kvOperatorName and kvResult overloads come in four variants that drop trailing optional parameters and apply default values. The table below shows what defaults are applied when you omit trailing parameters.

kvOperatorName overload variants

Signature (trailing params)OmittedDefaults applied
..., hasDefaultValue, fieldIsKv, maxKvCount)None
..., hasDefaultValue, fieldIsKv)maxKvCountmaxKvCount = 50
..., hasDefaultValue)fieldIsKv, maxKvCountfieldIsKv = true, maxKvCount = 50
..., mergeOperatorName)hasDefaultValue, fieldIsKv, maxKvCounthasDefaultValue = false, fieldIsKv = true, maxKvCount = 50

kvResult overload variants

Signature (trailing params)OmittedDefaults applied
..., hasDefaultValue, fieldIsKv, maxKvCount)None
..., hasDefaultValue, fieldIsKv)maxKvCountmaxKvCount = 50
..., hasDefaultValue)fieldIsKv, maxKvCountfieldIsKv = true, maxKvCount = 50
..., mergeOperatorName)hasDefaultValue, fieldIsKv, maxKvCounthasDefaultValue = false, fieldIsKv = true, maxKvCount = 50

evaluate()

double evaluate(OpsScoreParams params)

Matches request tags against document tags and returns the combined score. Call this in your scorer's score method.

ParameterTypeDescription
paramsOpsScoreParamsScore calculation parameters. See OpsScoreParams.

Code samples

All examples use the same init / score class structure. The only difference is the TagMatch.create() call.

Full parameter set — kvOperatorName overload

package users.scorer;
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.OpsDoc;
import com.aliyun.opensearch.cava.features.TagMatch;

class BasicSimilarityScorer {
    TagMatch _tagMatch;
    boolean init(OpsScorerInitParams params) {
        _tagMatch = TagMatch.create(params, "tag_match_key", "multi_int8", "query_value",
                                  "first_match", false, false, 100);
        return true;
    }

    double score(OpsScoreParams params) {
        return _tagMatch.evaluate(params);
    }
}

Default maxKvCount (50) — kvOperatorName overload

package users.scorer;
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.OpsDoc;
import com.aliyun.opensearch.cava.features.TagMatch;

class BasicSimilarityScorer {
    TagMatch _tagMatch;
    boolean init(OpsScorerInitParams params) {
        _tagMatch = TagMatch.create(params, "tag_match_key", "multi_int8", "query_value",
                                  "first_match", false, false);
        return true;
    }

    double score(OpsScoreParams params) {
        return _tagMatch.evaluate(params);
    }
}

Default fieldIsKv (true) and maxKvCount (50) — kvOperatorName overload

package users.scorer;
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.OpsDoc;
import com.aliyun.opensearch.cava.features.TagMatch;

class BasicSimilarityScorer {
    TagMatch _tagMatch;
    boolean init(OpsScorerInitParams params) {
        _tagMatch = TagMatch.create(params, "tag_match_key", "multi_int8", "query_value",
                                  "first_match", true);
        return true;
    }

    double score(OpsScoreParams params) {
        return _tagMatch.evaluate(params);
    }
}

All defaults — kvOperatorName overload

package users.scorer;
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.OpsDoc;
import com.aliyun.opensearch.cava.features.TagMatch;

class BasicSimilarityScorer {
    TagMatch _tagMatch;
    boolean init(OpsScorerInitParams params) {
        _tagMatch = TagMatch.create(params, "tag_match_key", "multi_int8", "query_value",
                                  "first_match");
        return true;
    }

    double score(OpsScoreParams params) {
        return _tagMatch.evaluate(params);
    }
}

Full parameter set — kvResult overload

package users.scorer;
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.OpsDoc;
import com.aliyun.opensearch.cava.features.TagMatch;

class BasicSimilarityScorer {
    TagMatch _tagMatch;
    boolean init(OpsScorerInitParams params) {
        _tagMatch = TagMatch.create(params, "tag_match_key", "multi_int8", 3.3D,
                                 "first_match", false, false, 100);
        return true;
    }

    double score(OpsScoreParams params) {
        return _tagMatch.evaluate(params);
    }
}

Default maxKvCount (50) — kvResult overload

package users.scorer;
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.OpsDoc;
import com.aliyun.opensearch.cava.features.TagMatch;

class BasicSimilarityScorer {
    TagMatch _tagMatch;
    boolean init(OpsScorerInitParams params) {
        _tagMatch = TagMatch.create(params, "tag_match_key", "multi_int8", 3.3D,
                                 "first_match", false, false);
        return true;
    }

    double score(OpsScoreParams params) {
        return _tagMatch.evaluate(params);
    }
}

Default fieldIsKv (true) and maxKvCount (50) — kvResult overload

package users.scorer;
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.OpsDoc;
import com.aliyun.opensearch.cava.features.TagMatch;

class BasicSimilarityScorer {
    TagMatch _tagMatch;
    boolean init(OpsScorerInitParams params) {
        _tagMatch = TagMatch.create(params, "tag_match_key", "multi_int8", 3.3D,
                                 "first_match", true);
        return true;
    }

    double score(OpsScoreParams params) {
        return _tagMatch.evaluate(params);
    }
}

All defaults — kvResult overload

package users.scorer;
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.OpsDoc;
import com.aliyun.opensearch.cava.features.TagMatch;

class BasicSimilarityScorer {
    TagMatch _tagMatch;
    boolean init(OpsScorerInitParams params) {
        _tagMatch = TagMatch.create(params, "tag_match_key", "multi_int8", 3.3D,
                                 "first_match");
        return true;
    }

    double score(OpsScoreParams params) {
        return _tagMatch.evaluate(params);
    }
}

Limitations

  • maxKvCount cannot exceed 5120.

  • The fieldName attribute field must store values as an integer or float array. If a float array is used, key values are cast to 64-bit integers during matching.

  • The search request must include a kvpairs clause; TagMatch does not apply to requests without one.

What's next