-
Notifications
You must be signed in to change notification settings - Fork 220
[Feature] Add user doc page for SQL vector search #5363
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
mengweieric
merged 8 commits into
opensearch-project:feature/vector-search-p0
from
mengweieric:pr/D-user-doc
Apr 27, 2026
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
a9ff2f8
Add user doc page for vectorSearch() table function
mengweieric 3396772
Address review: soften aggregation language; tighten filter_type sect…
mengweieric 2edee91
Correct vector-search doc to match current behavior
mengweieric 7ee62d2
Drop preview framing from Limitations section
mengweieric 289ec42
Tighten Limitations wording after dropping preview framing
mengweieric 2ebfa98
Align doc with current branch behavior after hardening PRs
mengweieric bd608f3
Align Limitations wording with house style
mengweieric 0715e42
Polish doc wording to match existing user-doc house style
mengweieric File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,283 @@ | ||
|
|
||
| ============= | ||
| Vector Search | ||
| ============= | ||
|
|
||
| .. rubric:: Table of contents | ||
|
|
||
| .. contents:: | ||
| :local: | ||
| :depth: 2 | ||
|
|
||
| Introduction | ||
| ============ | ||
|
|
||
| The ``vectorSearch()`` table function runs a k-NN query against a ``knn_vector`` | ||
| field and exposes the matching documents as a relation in the ``FROM`` clause. | ||
| It relies on the OpenSearch `k-NN plugin | ||
| <https://docs.opensearch.org/latest/vector-search/>`_ — the target index must | ||
| map the vector field as ``knn_vector`` and the index must be created with | ||
| ``index.knn: true``. | ||
|
|
||
| Relevance is expressed through the OpenSearch ``_score`` metadata field, and | ||
| results are returned ordered by ``_score DESC`` by default. | ||
|
|
||
| vectorSearch | ||
| ============ | ||
|
|
||
| Description | ||
| ----------- | ||
|
|
||
| ``vectorSearch(table='<index>', field='<vector-field>', vector='<array>', option='<key=value[,key=value]*>')`` | ||
|
|
||
| All four arguments are required and must be passed by name as string | ||
| literals. Positional arguments, or a mix of positional and named | ||
| arguments, are not supported. For example, the following is invalid:: | ||
|
|
||
| FROM vectorSearch('my_vectors', field='embedding', | ||
| vector='[0.1,0.2]', option='k=5') AS v | ||
|
|
||
| A table alias is required. Projected fields are referenced through the | ||
| alias (``v._id``, ``v._score``, ``v.category``). | ||
|
|
||
| If the ``opensearch-knn`` plugin is not installed on the target cluster, | ||
| query execution fails with a ``vectorSearch() requires the k-NN plugin`` | ||
| error. ``_explain`` continues to work without the plugin. | ||
|
|
||
| Arguments | ||
| --------- | ||
|
|
||
| - ``table`` — single concrete index or alias to search. Wildcards | ||
| (``*``), comma-separated multi-index targets, ``_all``, ``.``, and | ||
| ``..`` are not supported. The target index must have | ||
| ``index.knn: true`` and map the target field as ``knn_vector``. | ||
| - ``field`` — name of the ``knn_vector`` field. | ||
| - ``vector`` — query vector as a JSON-style array of numbers, passed as a | ||
| string (for example, ``'[0.1, 0.2, 0.3]'``). Components must be | ||
| comma-separated finite numbers. Semicolon, colon, and pipe separators | ||
| are not supported, and empty components (for example, ``'[1.0,,2.0]'`` | ||
| or ``'[1.0,]'``) return an error. The vector dimension must match the | ||
| ``knn_vector`` mapping on the target index. | ||
| - ``option`` — comma-separated ``key=value`` pairs. Exactly one of ``k``, | ||
| ``max_distance``, or ``min_score`` is required. ``filter_type`` is | ||
| optional. | ||
|
|
||
| Supported option keys | ||
| --------------------- | ||
|
|
||
| Option keys are lower-case and case-sensitive. ``K=5`` or | ||
| ``Filter_Type=post`` returns an "Unknown option key" error. | ||
|
|
||
| - ``k`` — top-k mode. Integer between 1 and 10000. The query returns up to | ||
| ``k`` nearest neighbors. | ||
| - ``max_distance`` — radial mode. Non-negative number. Returns all | ||
| documents within the given distance of the query vector. ``LIMIT`` is | ||
| required. | ||
| - ``min_score`` — radial mode. Non-negative number. Returns all documents | ||
| with score at or above the given threshold. ``LIMIT`` is required. | ||
| - ``filter_type`` — ``post`` or ``efficient``. Controls how a ``WHERE`` | ||
| clause is applied. See `Filtering`_. | ||
|
|
||
| ``k``, ``max_distance``, and ``min_score`` are mutually exclusive; specify | ||
| exactly one. | ||
|
|
||
| Native k-NN tuning options (for example, ``method_parameters.ef_search``, | ||
| ``method_parameters.nprobes``, ``rescore.oversample_factor``) are not | ||
| supported through ``vectorSearch()`` and return an "Unknown option | ||
| key" error. | ||
|
|
||
| Syntax | ||
| ------ | ||
|
|
||
| :: | ||
|
|
||
| SELECT <projection> | ||
| FROM vectorSearch( | ||
| table='<index>', | ||
| field='<vector-field>', | ||
| vector='<array>', | ||
| option='<key=value[,key=value]*>' | ||
| ) AS <alias> | ||
| [WHERE <predicate on alias non-vector fields>] | ||
| [ORDER BY <alias>._score DESC] | ||
| [LIMIT <n>] | ||
|
|
||
| Example 1: Top-k | ||
| ---------------- | ||
|
|
||
| Return the five nearest neighbors of a query vector:: | ||
|
|
||
| POST /_plugins/_sql | ||
| { | ||
| "query" : """ | ||
| SELECT v._id, v._score | ||
| FROM vectorSearch( | ||
| table='my_vectors', | ||
| field='embedding', | ||
| vector='[0.1, 0.2, 0.3]', | ||
| option='k=5' | ||
| ) AS v | ||
| """ | ||
| } | ||
|
|
||
| In top-k mode, the request size defaults to ``k``; adding ``LIMIT n`` further | ||
| reduces the row count, but ``n`` must not exceed ``k``. | ||
|
|
||
| Example 2: Radial search (``max_distance``) | ||
| ------------------------------------------- | ||
|
|
||
| Return every document within a maximum distance of the query vector. | ||
| ``LIMIT`` is required for radial searches — without it the result set is | ||
| unbounded:: | ||
|
|
||
| POST /_plugins/_sql | ||
| { | ||
| "query" : """ | ||
| SELECT v._id, v._score | ||
| FROM vectorSearch( | ||
| table='my_vectors', | ||
| field='embedding', | ||
| vector='[0.1, 0.2, 0.3]', | ||
| option='max_distance=0.5' | ||
| ) AS v | ||
| LIMIT 100 | ||
| """ | ||
| } | ||
|
|
||
| Example 3: Radial search (``min_score``) | ||
| ---------------------------------------- | ||
|
|
||
| Return every document whose score is at least the given threshold:: | ||
|
|
||
| POST /_plugins/_sql | ||
| { | ||
| "query" : """ | ||
| SELECT v._id, v._score | ||
| FROM vectorSearch( | ||
| table='my_vectors', | ||
| field='embedding', | ||
| vector='[0.1, 0.2, 0.3]', | ||
| option='min_score=0.8' | ||
| ) AS v | ||
| LIMIT 100 | ||
| """ | ||
| } | ||
|
|
||
| Filtering | ||
| ========= | ||
|
|
||
| A ``WHERE`` clause on non-vector fields of the ``vectorSearch()`` alias is | ||
| pushed down to OpenSearch when it can be translated to an OpenSearch filter. | ||
| Two placement strategies are available via the ``filter_type`` option: | ||
|
|
||
| - ``post`` — the ``WHERE`` predicate is applied as a non-scoring | ||
| ``bool.filter`` alongside the k-NN query. The k-NN query runs first and | ||
| its results are then filtered. | ||
| - ``efficient`` — the ``WHERE`` predicate is embedded directly inside the | ||
| k-NN query (``knn.filter``), enabling pre-filtering during the ANN search. | ||
| See the `k-NN filtering guide <https://docs.opensearch.org/latest/vector-search/filter-search-knn/efficient-knn-filtering/>`_ | ||
| for engine and method requirements. | ||
|
|
||
| Behavior depends on whether ``filter_type`` is specified: | ||
|
|
||
| - **Omitted** — pushdown is attempted using the ``post`` placement. | ||
| Predicates that translate to native OpenSearch queries are pushed down as a | ||
| ``bool.filter`` alongside the k-NN query. Predicates that do not have a | ||
| native equivalent (for example, arithmetic or function calls on indexed | ||
| fields) are pushed down as an OpenSearch script query and evaluated | ||
| server-side. Only when predicate translation itself fails does the engine | ||
| fall back to evaluating the ``WHERE`` clause in memory after the k-NN | ||
| results are returned. A query with no ``WHERE`` clause is valid. | ||
| - **Explicit ``post``** — a ``WHERE`` clause is required and must be | ||
| translatable to an OpenSearch filter query. If the ``WHERE`` clause is | ||
| missing or cannot be translated, the query fails with an error. | ||
| Specifying ``filter_type=post`` explicitly is useful when the query | ||
| should fail with an error instead of silently falling back to | ||
| in-memory filtering. | ||
| - **Explicit ``efficient``** — a ``WHERE`` clause is required and must | ||
| compile to a filter shape that can be embedded under ``knn.filter``. | ||
| ``efficient`` supports simple native filters: ``term``, ``range``, | ||
| ``wildcard``, ``exists``, full-text family (``match``, ``match_phrase``, | ||
| ``match_phrase_prefix``, ``match_bool_prefix``, ``multi_match``, | ||
| ``query_string``, ``simple_query_string``), and boolean combinations of | ||
| those filters. Predicates that compile to script queries (arithmetic, | ||
| function calls, ``CASE``, date math), nested predicates, and other | ||
| query shapes are not supported in this mode and return an error. | ||
|
|
||
| Example 4: Implicit pushdown (no ``filter_type``) | ||
| ------------------------------------------------- | ||
|
|
||
| :: | ||
|
|
||
| POST /_plugins/_sql | ||
| { | ||
| "query" : """ | ||
| SELECT v._id, v._score, v.category | ||
| FROM vectorSearch( | ||
| table='my_vectors', | ||
| field='embedding', | ||
| vector='[0.1, 0.2, 0.3]', | ||
| option='k=10' | ||
| ) AS v | ||
| WHERE v.category = 'books' | ||
| """ | ||
| } | ||
|
|
||
| Example 5: Efficient (pre-)filtering | ||
| ------------------------------------ | ||
|
|
||
| :: | ||
|
|
||
| POST /_plugins/_sql | ||
| { | ||
| "query" : """ | ||
| SELECT v._id, v._score, v.category | ||
| FROM vectorSearch( | ||
| table='my_vectors', | ||
| field='embedding', | ||
| vector='[0.1, 0.2, 0.3]', | ||
| option='k=10,filter_type=efficient' | ||
| ) AS v | ||
| WHERE v.category = 'books' | ||
| """ | ||
| } | ||
|
|
||
| Scoring, sorting, and limits | ||
| ============================ | ||
|
|
||
| - ``vectorSearch()`` exposes the OpenSearch ``_score`` metadata field on the | ||
| alias. Select it as ``<alias>._score``. | ||
| - ``_score`` can be selected and referenced in ``ORDER BY``, but it cannot | ||
| appear in ``WHERE``. Use ``option='min_score=...'`` for score-threshold | ||
| vector search. | ||
| - Results are returned in ``_score DESC`` order by default. The only | ||
| supported ``ORDER BY`` expression is ``<alias>._score DESC``. | ||
| - In top-k mode (``k=N``), ``LIMIT n`` is optional; when present, ``n`` must | ||
| be ``≤ k``. | ||
| - In radial mode (``max_distance`` or ``min_score``), ``LIMIT`` is required. | ||
| - ``OFFSET`` is not supported on ``vectorSearch()``. Use ``LIMIT`` only. | ||
|
|
||
| Limitations | ||
| =========== | ||
|
|
||
| The following are not supported on ``vectorSearch()``: | ||
|
|
||
| - ``GROUP BY`` and aggregations over a ``vectorSearch()`` relation are | ||
| not supported and return an error. | ||
| - An outer ``WHERE`` clause applied to a ``vectorSearch()`` subquery is | ||
| not supported and returns an error, because the predicate would be | ||
| evaluated only after the top-k rows have been selected by vector | ||
| distance and can silently yield zero rows. Place the predicate inside | ||
| the subquery, directly on the ``vectorSearch()`` alias, so that it | ||
| participates in ``WHERE`` pushdown. | ||
| - ``JOIN`` between a ``vectorSearch()`` relation and another relation is | ||
| not supported. | ||
| - ``UNION`` / ``INTERSECT`` / ``EXCEPT`` combining a ``vectorSearch()`` | ||
| relation with another relation is not supported. | ||
| - Multiple ``vectorSearch()`` calls in the same query are not supported. | ||
| - The query vector must be supplied as a literal. Parameterized vectors | ||
| (for example, values bound from another column) are not supported. | ||
| - Indexes that define a user field named ``_score`` cannot be queried | ||
| with ``vectorSearch()`` because ``_score`` is reserved for the | ||
| synthetic vector score exposed on the alias. Rename the field or query | ||
| the index with a plain ``SELECT``. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.