Skip to main content

Vector Top-K

UDTF: cuvs_top_k

Official cuVS reference: C++ API

Select the smallest or largest values in every dense vector row.

Quickstart​

The call below expects the registered relation input_vectors (the input role), passed as a parenthesized SELECT subquery.

SELECT *
FROM cuvs_top_k(
input => (SELECT id, d0, d1 FROM input_vectors),
k => 1,
select => 'max'
)
ORDER BY row_ordinal, rank;

Inputs​

Each relation argument is a parenthesized SELECT subquery that the planner keeps as an operator child. Metadata validation resolves a registered table or view for the same role. See Vector Inputs for the relation identity rules and the ID, dense-vector type, null, finite-value, and runtime-dimension contract.

RoleRequiredValidation referenceDescription
inputyestableDense-vector rows consumed by this operation.

Vector element types​

Feature values must be Float32.

Arguments and options​

Scalar SQL arguments​

ArgumentTypeRequiredDefaultConstraintsDescription
kintegeryesNo defaultminimum 1; maximum 4294967295Number of values selected from each row.
selectstringyesNo defaultone of "min", "max"Select the minimum or maximum values.

Vector binding shapes​

Each relation subquery must project an id field followed by either one or more feature fields of a supported element type (Float32) or one list field of a supported element type, under any name.

For wide vectors, the projection order defines the feature dimensions. A list vector relation must contain no feature field beside id and its list field. Nullable field types are accepted. A null ID, feature value, list row, or list element fails the query.

Output​

ColumnTypeNullableDescription
row_ordinalUInt64noZero-based physical ordinal of the evaluated input row; it disambiguates duplicate input IDs. Follows the input's top-level ORDER BY on output columns; unspecified without one.
idsame_as_input.idnoLogical ID copied from the input relation.
rankUInt32noOne-based value rank within an input row. Order consumers explicitly by row_ordinal, rank.
positionInt64noZero-based dimension index of the selected value within the input vector.
valueFloat32noSelected Float32 input vector value; rank follows ascending values for min and descending values for max.

The output schema depends on the call. Run gpu_validate_call against registered relations to inspect the schema that the validated ID types and literal options produce.

Examples​

This example reads the raw products and reviews tables from the Amazon Reviews demo dataset. It does not use prepared text embeddings.

Which review themes describe each group of products?​

The saved query groups 2,384 products by eight keyword-mention rates in their 2022 low-rating reviews. It returns the three largest average rates for each of six groups. One group has the following profile:

RankIssue mentionedMean product mention rate
1Durability35.99%
2Sound18.61%
3Returns11.23%

Another group leads with sound at 45.10%, followed by charging at 24.20% and connection at 24.09%. These rates suggest which original reviews an analyst should read. They are averages of product-level rates. A product with ten reviews has the same weight as a product with a thousand.

SQL filters headphones and accessories with at least ten low-rating reviews, calculates eight substring rates for each product, and fits KMeans to those rates. It then averages each group's product profiles. Top-K returns the three largest dimensions within each profile, rather than across all groups. No predefined complaint labels enter this query.

Read the query: review mentions → KMeans → Top-K
WITH complaint_features AS (
SELECT
p.product_id AS id,
COUNT(*) AS negative_reviews,
CAST(AVG(CASE WHEN LOWER(r.text) LIKE '%battery%' THEN 1.0 ELSE 0.0 END) AS REAL) AS battery,
CAST(AVG(CASE WHEN LOWER(r.text) LIKE '%connect%' OR LOWER(r.text) LIKE '%bluetooth%' THEN 1.0 ELSE 0.0 END) AS REAL) AS connection,
CAST(AVG(CASE WHEN LOWER(r.text) LIKE '%sound%' OR LOWER(r.text) LIKE '%volume%' THEN 1.0 ELSE 0.0 END) AS REAL) AS sound,
CAST(AVG(CASE WHEN LOWER(r.text) LIKE '%comfort%' OR LOWER(r.text) LIKE '%fit%' THEN 1.0 ELSE 0.0 END) AS REAL) AS comfort,
CAST(AVG(CASE WHEN LOWER(r.text) LIKE '%broke%' OR LOWER(r.text) LIKE '%stopped working%' THEN 1.0 ELSE 0.0 END) AS REAL) AS durability,
CAST(AVG(CASE WHEN LOWER(r.text) LIKE '%charg%' THEN 1.0 ELSE 0.0 END) AS REAL) AS charging,
CAST(AVG(CASE WHEN LOWER(r.text) LIKE '%microphone%' OR LOWER(r.text) LIKE '%mic %' THEN 1.0 ELSE 0.0 END) AS REAL) AS microphone,
CAST(AVG(CASE WHEN LOWER(r.text) LIKE '%return%' OR LOWER(r.text) LIKE '%refund%' THEN 1.0 ELSE 0.0 END) AS REAL) AS returns
FROM reviews AS r
JOIN products AS p
ON r.product_id = p.product_id
WHERE p.category_l2 = 'Headphones, Earbuds & Accessories'
AND r.review_time >= TIMESTAMP '2022-01-01 00:00:00'
AND r.review_time < TIMESTAMP '2023-01-01 00:00:00'
AND r.rating <= 2
AND r.text IS NOT NULL
GROUP BY p.product_id
HAVING COUNT(*) >= 10
),

clusters AS (
SELECT
id,
cluster_id
FROM cuvs_kmeans(
input => (
SELECT
id,
COALESCE(battery, CAST(0 AS REAL)) AS battery,
COALESCE(connection, CAST(0 AS REAL)) AS connection,
COALESCE(sound, CAST(0 AS REAL)) AS sound,
COALESCE(comfort, CAST(0 AS REAL)) AS comfort,
COALESCE(durability, CAST(0 AS REAL)) AS durability,
COALESCE(charging, CAST(0 AS REAL)) AS charging,
COALESCE(microphone, CAST(0 AS REAL)) AS microphone,
COALESCE(returns, CAST(0 AS REAL)) AS returns
FROM complaint_features
ORDER BY id
),
n_clusters => 6,
n_init => 5
)
),

profiles AS (
SELECT
CAST(k.cluster_id AS BIGINT) AS id,
COALESCE(CAST(AVG(c.battery) AS REAL), CAST(0 AS REAL)) AS battery,
COALESCE(CAST(AVG(c.connection) AS REAL), CAST(0 AS REAL)) AS connection,
COALESCE(CAST(AVG(c.sound) AS REAL), CAST(0 AS REAL)) AS sound,
COALESCE(CAST(AVG(c.comfort) AS REAL), CAST(0 AS REAL)) AS comfort,
COALESCE(CAST(AVG(c.durability) AS REAL), CAST(0 AS REAL)) AS durability,
COALESCE(CAST(AVG(c.charging) AS REAL), CAST(0 AS REAL)) AS charging,
COALESCE(CAST(AVG(c.microphone) AS REAL), CAST(0 AS REAL)) AS microphone,
COALESCE(CAST(AVG(c.returns) AS REAL), CAST(0 AS REAL)) AS returns
FROM clusters AS k
JOIN complaint_features AS c
ON k.id = c.id
GROUP BY k.cluster_id
)

SELECT
t.id AS cluster_id,
t.rank,
CASE t.position
WHEN 0 THEN 'battery'
WHEN 1 THEN 'connection'
WHEN 2 THEN 'sound'
WHEN 3 THEN 'comfort'
WHEN 4 THEN 'durability'
WHEN 5 THEN 'charging'
WHEN 6 THEN 'microphone'
WHEN 7 THEN 'returns'
END AS issue,
t.value AS mean_product_mention_rate
FROM cuvs_top_k(
input => (
SELECT
id,
battery,
connection,
sound,
comfort,
durability,
charging,
microphone,
returns
FROM profiles
),
k => 3,
select => 'max'
) AS t
ORDER BY
t.id,
t.rank;

position = 5 means charging because charging is the sixth projected feature.

The saved output contains all six groups.

Each rate counts reviews containing an English substring. Negation is not resolved, and one review can mention several themes. Mentions of returns do not establish a completed return transaction.

Limits​

  • k must not exceed the vector dimension. Empty input returns an empty result with the stable schema.
  • Equal selected values are ordered by position; when ties straddle rank k, the selected positions among them are unspecified.