Hybrid query based on vectors and text

更新时间:
复制 MD 格式

A hybrid query combines k-nearest neighbor (kNN) vector search with text keyword search in a single request. Use it when queries mix natural language with exact terms, product names, or IDs — cases where neither pure vector search nor pure text search alone provides sufficient recall and precision.

Query syntax

URL

POST /search
POST /vector-service/search
The URLs above omit request header parameters, encoding details, and the endpoint used to connect to your OpenSearch instance. See Request parameters for the full parameter reference.

Protocol

HTTP

Request method

POST

Supported format

JSON

Authentication

Sign requests using HTTP Basic authentication. Encode your credentials as Base64 and include the result in the authorization header.

ParameterTypeDescription
accessUserNamestringYour username. View it in the API Endpoint section of the Instance Details page.
accessPassWordstringYour password. Modify it in the API Endpoint section of the Instance Details page.

The following Java snippet generates the Base64-encoded credential string:

import com.aliyun.darabonba.encode.Encoder;
import com.aliyun.darabonbastring.Client;

public class GenerateAuthorization {

    public static void main(String[] args) throws Exception {
        String accessUserName = "username";
        String accessPassWord = "password";
        String realmStr = accessUserName + ":" + accessPassWord;
        String authorization = Encoder.base64EncodeToString(Client.toBytes(realmStr, "UTF-8"));
        System.out.println(authorization);
    }
}

The encoded value looks like:

cm9vdDp******mdhbA==

Add the Basic prefix when setting the header in your HTTP request:

authorization: Basic cm9vdDp******mdhbA==

Request parameters

ParameterTypeRequiredDefaultDescription
tableNamestringYesThe name of the table to query.
knnobjectNoThe kNN query parameters.
knn.vectorlist[float]Yes (if knn is set)The dense vector to query.
knn.topkintNoThe number of results to be returned.
knn.filterstringNo""A filter expression applied to kNN results.
knn.weightfloatNo1.0The weight of kNN query results. The result of the score multiplied by the weight is used as the sorting score.
textobjectNoThe text query parameters.
text.queryStringstringYes (if text is set)A query expression using HA3 query clause syntax. Supports AND and OR operators across multiple text indexes.
text.queryParamsmap[string, string]No{}Additional text query parameters. See text.queryParams sub-parameters.
text.filterstringNo""A filter expression applied to text results.
text.weightfloatNo1.0The weight of text query results. The result of the score multiplied by the weight is used as the sorting score.
text.terminateAfterintegerNo0The maximum number of documents to scan per shard before stopping. 0 means no limit.
sizeintegerNo100The number of results to return.
fromintegerNo0The offset into the result set.
outputFieldslist[string]No[]The fields to include in the response.
orderstringNoDESCThe sort order: DESC (descending) or ASC (ascending).
rankobjectNo{}The merge policy for combining kNN and text result sets. See Choose a merge strategy.

text.queryParams sub-parameters

Sub-parameterDescriptionValid valuesDefault
default_opThe logical operator between terms after tokenization.AND, ORAND
no_token_indexesFields whose values are not converted to terms. Normalization and stop word removal still apply. Separate multiple fields with semicolons (;).Field names
remove_stopwordsSpecifies whether to remove stop words during analysis.true, falsetrue

Usage notes

  • kNN supports single-vector queries only. Query parameters follow the same conventions as standard API queries.

  • Before combining kNN and text scores, convert raw kNN scores using the formula for your distance metric:

    # Euclidean distance (L2)
    score = 1.0 / (1.0 + l2_distance^2)
    
    # Inner product distance
    score = (1.0 + ip_distance) / 2.0
  • The order parameter inside the knn object has no effect. The top-level order parameter controls sort direction.

Choose a merge strategy

Two strategies are available for combining kNN and text result sets:

StrategyHow it worksUse when
Weighted score (default)Multiplies each result's raw score by its weight, then sums scores for documents that appear in both sets.Your distance metric produces meaningful absolute scores and you want predictable, tunable blending via knn.weight and text.weight.
Reciprocal rank fusion (RRF)Combines results based on rank position rather than raw score. A smoothing constant (rankConstant) controls how much low-ranked results influence the final score.Raw scores from kNN and text are not directly comparable, or you want rank-based blending that is robust to score-scale differences.

Weighted score (default)

Leave rank empty or omit it entirely:

{
  "rank": {}
}

Final score formula:

score(i) = knn_score(i) * knn_weight + text_score(i) * text_weight

Adjust knn.weight and text.weight to shift influence between the two result sets. Both default to 1.0 (equal weighting).

Reciprocal rank fusion (RRF)

{
  "rank": {
    "rrf": {
      "rankConstant": 60
    }
  }
}

rankConstant is optional and defaults to 60 (minimum: 1). A larger value gives low-ranked documents more influence on the final score.

RRF score formula:

score = 0.0
if d in result(q):
    score += 1.0 / (rankConstant + rank(result(q), d))
return score

# rank(result(q), d) is the 1-based position of document d in result set q.

Query example

{
    "tableName": "test",
    "text": {
        "queryString": "title:'Alibaba'",
        "queryParams": {
            "default_op": "OR"
        },
        "filter": "count > 0",
        "terminateAfter": 100000
    },
    "knn": {
        "vector": [0.1, 0.2, 0.3, 0.4, 0.5],
        "namespace": "1",
        "topK": 100
    },
    "order": "DESC",
    "size": 10,
    "rank": {
        "rrf": {
            "rankConstant": 1
        }
    },
    "outputFields": ["title"]
}

Response

Example response

{
  "totalTime": 8.522,
  "coveredPercent": 1.0,
  "totalCount": 5,
  "result": [
    {
      "__source__": 2,
      "score": 0.833333,
      "namespace": 1,
      "id": 2,
      "fields": {
        "title": "a b c"
      }
    },
    {
      "__source__": 3,
      "score": 0.666666,
      "namespace": 1,
      "id": 1,
      "fields": {
        "title": "a b"
      }
    },
    {
      "__source__": 3,
      "score": 0.333333,
      "namespace": 2,
      "id": 5,
      "fields": {
        "title": "c"
      }
    },
    {
      "__source__": 2,
      "score": 0.25,
      "namespace": 2,
      "id": 4,
      "fields": {
        "title": "b c"
      }
    },
    {
      "__source__": 2,
      "score": 0.2,
      "namespace": 1,
      "id": 0,
      "fields": {
        "title": "a"
      }
    }
  ]
}

Response parameters

FieldTypeDescription
idSchema-configured typeThe primary key value.
namespaceSchema-configured typeThe namespace of the kNN vector index queried. Returned only when a namespace is configured.
vectorlist[float]The vector index value. Returned only when "includeVector": true is set in the kNN query.
scorefloatThe final ranking score.
fieldsmap[string, field_type]The returned fields in key-value format.
totalTimeintegerThe response time in milliseconds.
totalCountintegerThe total number of matched results.
__source__integerThe query source for each result: 1 = kNN only, 2 = text only, 3 = both kNN and text.
coveredPercentfloatThe fraction of shards that returned data successfully. 1.0 means all shards responded.