Search
This page covers every way to read and prune data in a VectorDB index: similarity queries, payload filters, score thresholds, paging through raw points, and deleting points. Each pattern comes with a runnable request and its expected output.
All examples assume the setup from the quickstart:
export VDB="$CAI_VECTORDB_API"
export TOKEN="$CAI_TOKEN"
export PROJECT="00000000-0000-0000-0000-000000000000" # your project UUID
and an index named docs with 4 dimensions containing:
{"points":[
{"id":1,"vector":[0.1,0.2,0.3,0.4],"payload":{"tag":"alpha"}},
{"id":2,"vector":[0.9,0.8,0.7,0.6],"payload":{"tag":"beta"}}]}
Nearest-neighbor search
A query takes a vector and returns the points closest to it, best first. This is called ANN search — approximate nearest neighbor — "approximate" because the engine uses a smart shortcut structure instead of comparing your query against every stored vector, trading a tiny bit of accuracy for a lot of speed.
curl -sX POST "$VDB/v1/projects/$PROJECT/indexes/docs:query" \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"vector":[0.1,0.2,0.3,0.4],"top_k":5}'
You should see:
{"index":"docs","results":[{"id":1,"score":1.0,"payload":{"tag":"alpha"}},{"id":2,"score":...,"payload":{"tag":"beta"}}]}
Request fields
| Field | Type | Default | Notes |
|---|---|---|---|
vector | array of numbers | required | Must match the index's dimensions exactly |
top_k | integer | 10 | How many nearest points to return; max 1000 |
filter | JSON object | none | Payload filter (below); max 64 KiB |
with_payload | boolean | true | Include each hit's payload |
with_vector | boolean | false | Include each hit's stored vector |
score_threshold | number | none | Drop hits scoring below this value |
offset | integer | 0 | Skip the first N hits (must not be negative) |
Scores
Every hit carries a score computed with the index's distance metric. Results are ordered best first. With cosine, an identical vector scores a perfect 1.0 — which is why the quickstart's exact-match query returns "score":1.0. Use score_threshold to cut off weak matches instead of post-filtering client-side:
curl -sX POST "$VDB/v1/projects/$PROJECT/indexes/docs:query" \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"vector":[0.1,0.2,0.3,0.4],"top_k":10,"score_threshold":0.9}'
You should see only the strong match:
{"index":"docs","results":[{"id":1,"score":1.0,"payload":{"tag":"alpha"}}]}
Payload filters
A filter restricts search to points whose payload matches a condition — "nearest neighbors, but only among documents tagged alpha". Filters use the Qdrant filter syntax: a JSON object with clauses like must containing conditions that pair a payload key with a match:
curl -sX POST "$VDB/v1/projects/$PROJECT/indexes/docs:query" \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"vector":[0.5,0.5,0.5,0.5],"top_k":5,
"filter":{"must":[{"key":"tag","match":{"value":"beta"}}]}}'
You should see:
{"index":"docs","results":[{"id":2,"score":...,"payload":{"tag":"beta"}}]}
Filter rules:
- The filter must be a JSON object (400
filter must be a JSON object). - It is capped at 64 KiB (400
filter is too large). - Filter mistakes the engine itself rejects come back as 400
vector database rejected the request: <engine message>— the engine's own explanation is passed through verbatim so you can fix the actual problem.
Browsing without a query: scroll
Scroll lists points in id order — no vector needed. It's the "just show me what's in here" operation, and it's what the console's Data browser uses.
curl -sX POST "$VDB/v1/projects/$PROJECT/indexes/docs:scroll" \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"limit":50}'
You should see:
{"index":"docs","points":[{"id":1,"payload":{"tag":"alpha"}},{"id":2,"payload":{"tag":"beta"}}],"next_offset":...}
limitdefaults to 50, max 1000 (400limit must be at most 1000).- Scrolled points carry payloads but never vectors.
- Pagination: when there are more points, the response includes
next_offset(a point id). Send it back asoffsetin your next request. Whennext_offsetis absent, you've seen everything. Sending a malformed offset gets 400offset must be an unsigned integer or a UUID string.
Deleting points
Delete by explicit ids or by filter — exactly one of the two:
curl -sX POST "$VDB/v1/projects/$PROJECT/indexes/docs:delete-points" \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"ids":[1]}'
You should see:
{"index":"docs","status":"ok","ids_requested":1}
Or by filter:
curl -sX POST "$VDB/v1/projects/$PROJECT/indexes/docs:delete-points" \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"filter":{"must":[{"key":"tag","match":{"value":"beta"}}]}}'
You should see:
{"index":"docs","status":"ok"}
Rules:
- Provide exactly one of
idsorfilter(400provide exactly one of ids or filter). - At most 1000 ids per request (400
at most 1000 ids per request). - An empty filter is deliberately refused, because it would match everything:
{"error":"an empty filter would delete every point; delete the index instead if that is the intent","request_id":"..."}
Common errors at a glance
| Symptom (verbatim error) | Cause | Fix |
|---|---|---|
index is not ready yet; its collection has not been created | Querying right after create | Poll GET .../indexes/{name} until ready: true |
query vector has N dimensions; index "docs" expects M | Query vector from the wrong embedding model | Embed queries with the same model you indexed with |
top_k must be at most 1000 | Asking for too many results | Page with offset, or rethink why you need 1000+ neighbors |
filter is too large | Filter over 64 KiB | Simplify the filter; move logic into payload design |
offset must not be negative | Negative offset in a query | Use 0 or a positive integer |
Trying queries in the console
Each index's detail page in the console (Data services → VectorDB → your index) has a Query panel: paste a vector (JSON array or comma/space-separated numbers), set Top K and an optional payload filter, and use the "Fill with a random vector" button for a quick smoke test. The Data browser tab walks scroll pages and offers per-point delete.
Next steps
- Indexes and points — the data model behind these queries.
- Use with agents — semantic search as agent memory.
- API reference — the full endpoint reference.