Docs
Skip to content

VectorsDB

Vector search_

Run similarity search over your documents with Appwrite VectorsDB. Create an HNSW index on the embeddings field and rank documents by cosine, dot product, or Euclidean distance.

4 min read

Raw

Vector search finds the documents whose embeddings are closest to a query vector. Instead of matching exact values, it ranks documents by similarity, so you can build features like semantic search, recommendations, and retrieval for AI applications.

There are two steps: create an index on the embeddings field so searches are fast, then pass a vector query to listDocuments to get documents ranked by similarity.

Create an index

Before you search, create an HNSW index on the embeddings field with createIndex. HNSW (Hierarchical Navigable Small World) is an approximate nearest neighbor index that keeps similarity search fast as your collection grows.

The index type decides how similarity is measured. Use the VectorsDBIndexType enum to pick one:

Index typeEnumUse when
hnsw_cosineVectorsDBIndexType.HnswCosineYou care about the direction of the vectors, not their magnitude. A common default for text embeddings.
hnsw_dotVectorsDBIndexType.HnswDotYou want the dot product, which factors in both direction and magnitude.
hnsw_euclideanVectorsDBIndexType.HnswEuclideanYou want the straight-line distance between vectors.

Match the index type to the search query you plan to run. A hnsw_cosine index serves Query.vectorCosine searches, hnsw_dot serves Query.vectorDot, and hnsw_euclidean serves Query.vectorEuclidean.

The index is built in the background. New documents are added to the index as you create them, so you can keep writing while it builds.

To search, pass a vector query to listDocuments. Build the query with one of the Query vector methods, passing the field name embeddings and the query vector. The response returns documents ranked from most to least similar.

Query methodUse with index type
Query.vectorCosine('embeddings', vector)hnsw_cosine
Query.vectorDot('embeddings', vector)hnsw_dot
Query.vectorEuclidean('embeddings', vector)hnsw_euclidean

The query vector must have the same dimension as the collection. You can combine the vector query with other queries, such as Query.limit() to cap how many results you get back.

To rank by dot product or Euclidean distance instead, swap vectorCosine for vectorDot or vectorEuclidean, and make sure your index uses the matching type.

Read the distance

A vector query adds a $distance field to every document it returns, and the results come back sorted by it, closest first. Documents returned without a vector query have no $distance.

JSON
{
"$id": "6a86ebc8002fb1efb979",
"$distance": 0.1308663759554639,
"embeddings": [0.12, 0.84, 0.33, 0.57],
"metadata": { "title": "Getting started with Appwrite" }
}

The scale depends on the query method, so compare $distance values only within one set of results:

Query methodWhat $distance measuresClosest value
Query.vectorCosineCosine distance0
Query.vectorDotNegative inner productMost negative
Query.vectorEuclideanStraight-line distance0

Use $distance to drop weak matches, for example by keeping only the results below a cutoff you pick from your own data.

Send queries in the request body

listDocuments puts your queries in the URL, so a long query vector makes for a long URL. A 768-dimension vector serializes to roughly 9 KB of query string and a 2,000-dimension vector to roughly 40 KB, both of which the server accepts. Past a few thousand dimensions the URL grows beyond what the server will read and the request fails with a 400.

createQuery takes the same queries in the request body instead, so the size of the query vector no longer matters. It returns the same document list as listDocuments, and it accepts the same transactionId and ttl options.

Use createQuery when you store high-dimension vectors or send many queries at once. For the dimensions the built-in embedding models produce, either method works.

Manage indexes

A collection starts with an object index on metadata, and listIndexes returns it alongside any index you create. Use these methods to see which indexes a collection has, check whether one has finished building, and remove indexes you no longer query against.

List indexes

Each entry has a key, a type, the attributes it covers, and a status: available, processing, deleting, stuck, or failed.

Get index

Read a single index by its key. The status field tells you whether the index is ready, and error holds the reason when creating or deleting an index fails.

Delete index

Deleting an index leaves your documents untouched. Searches that relied on it fall back to a slower scan, so replace an index before you drop it if the collection is serving traffic.

Next steps

Vector search ranks documents by similarity. To filter those results by the data stored alongside each vector, combine search with metadata queries.

Was this page helpful?

Share what worked or what we should fix. Once approved, our agents automatically apply suggested updates to the docs.