Search within matching metadata
The language tabs use earlier client interfaces. Check SDK versions and connection setup before running them.
Combine similarity with exact metadata filters. The search returns up to k qualifying matches.
Before you run it: These are flat equality filters, not ranges or an authorization boundary. Missing or differently cased values do not match.
First write metadata. That recipe stores category: "running-shoes", while the request below filters for "shoes". Change the filter to "running-shoes" to match that sample, or deliberately write the category used here. An empty result with mismatched values is expected, not an indexing failure.
- Read the stored metadataThe linked sample uses category running-shoes.
- Match the filter spellingUse that category and any required stock value exactly.
- Search the qualifying vectorsSupply the query embedding and matching metadata conditions.
- Inspect up to k IDsFewer results or an empty list can be valid.
Follow the example
- Write metadata with each vector.
- Choose the required metadata values.
- Send the query vector and filter.
- Check IDs and result count.
Run the request
curl -X POST "https://$OC_HOST/v1/tenants/$OC_TENANT/vector/shop.products/topk" \
-H "Authorization: Bearer $OC_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": [0.0124, -0.0883, 0.0451, /* ... 768 floats ... */],
"k": 10,
"dim": 768,
"metric": "cosine",
"filter": { "category": "shoes" }
}'Check the result
Every returned hit must match all filter keys. The result can contain fewer than k hits because of the available data, search limits or access rules.
[
{ "id": "sku-9281", "score": 0.9421 },
{ "id": "sku-1144", "score": 0.9187 }
]The HTTP response is a JSON array of hits, with no hits wrapper. The IDs and scores above illustrate the shape; your stored data determines the results.
The shape matches unfiltered top-k. There is no padding, and the returned count is not an exhaustive count of every matching vector.
Filter limits
| Rule | Notes |
|---|---|
| This example uses the equality map | Supply key: value pairs in filter. Typed conditions use the separate filter_expr field where supported. |
| Multiple keys are AND | { "category": "shoes", "in_stock": true } means both must match. |
| Exact match, case-sensitive | "Shoes" does not match "shoes". Normalise on insert. |
| Strings, numbers, booleans | Nested objects and arrays are not filterable. Flatten at put time. |
Important limits and checks
- Range filters in the equality map.
filterdoes not accept operators. Use the typed-filter contract where supported; do not send it together with a non-empty equality map. - Case-mismatched values. Filter values must match exactly.
"shoes"and"Shoes"are different. Lowercase on the way in. - Filtering on a field that was never stored. The filter doesn't error - it just matches nothing, and you get an empty hits array. Double-check the metadata was set when you called put.