Skip to content
Back to catalog
Qdrant

Vector search with Qdrant

Sync an Appwrite Databases table to a Qdrant collection and search it by meaning with OpenAI embeddings

Qdrant is an open-source vector database written in Rust. It stores embeddings with a JSON payload and returns the points closest to a query vector, which makes it a good fit for semantic search and retrieval-augmented generation. You can run it yourself or use the managed Qdrant Cloud.

How does the integration work?

The Sync with Qdrant recipe is an Appwrite Function from the Appwrite templates repository. When you send it a POST request, it reads every row of an Appwrite Databases table, creates an embedding for each row with OpenAI's text-embedding-3-small model, and upserts the embeddings into a Qdrant collection with the full row as the payload.

RoutePurpose
GET /Serves a demo page where you can search the collection
POST /Syncs the table to Qdrant
POST /searchEmbeds the prompt in the JSON body and returns the 5 closest points with their payloads

Prerequisites

  • An Appwrite database with a table that holds the data you want to search.
  • A Qdrant instance the function can reach, such as a Qdrant Cloud cluster.
  • An OpenAI API key. OpenAI bills each embeddings request.
  • Git and tar on your machine.

How to implement

To implement the Qdrant integration, there are several steps you must complete:

Step 1: Set up Qdrant

Create a Qdrant Cloud cluster, or start your own Qdrant server. Copy the cluster URL, including the port (for example https://<CLUSTER_HOST>:6333), and create an API key for it.

The recipe doesn't create the collection, so create one with a vector size of 1536, the size of text-embedding-3-small embeddings:

Bash
curl -X PUT "https://<CLUSTER_HOST>:6333/collections/<COLLECTION_NAME>" \
-H "api-key: <QDRANT_API_KEY>" \
-H "Content-Type: application/json" \
-d '{"vectors": {"size": 1536, "distance": "Cosine"}}'

Step 2: Deploy the recipe

For this step, you must create an account on Appwrite Cloud or self-host Appwrite if you haven't already.

Download the released recipe and package it as a .tar.gz archive:

Bash
git clone --depth 1 --branch 1.2.0 https://github.com/appwrite/templates.git
cd templates/node/sync-with-qdrant
tar --exclude code.tar.gz -czf code.tar.gz .

In the Appwrite Console, go to Functions, click Create function, and choose create a function manually. Pick a Node.js runtime, version 18.17 or later, upload code.tar.gz, and set the entrypoint to src/main.js and the build command to npm install. Unless the table's data is public, don't allow anyone to execute the function. Then click Create and deploy.

You can also deploy the folder with the Appwrite CLI, or copy it into your own repository and deploy it from Git.

Step 3: Configure variables and scopes

Open the function's Settings tab. Under Environment variables, add:

VariableValue
APPWRITE_DATABASE_IDThe ID of the database that holds your table
APPWRITE_COLLECTION_IDThe ID of the table to sync. The recipe reads it through the legacy Databases API, which calls tables collections.
QDRANT_URLYour cluster URL
QDRANT_API_KEYYour Qdrant API key
QDRANT_COLLECTION_NAMEThe collection you created
OPENAI_API_KEYYour OpenAI API key

The recipe reads your table with the function's ephemeral API key. Under Scopes, grant the read scopes the in-console sync templates use: databases.read, collections.read, tables.read, documents.read, and rows.read. Then redeploy the function so the variables take effect.

To start the sync, execute the function from the Console with the POST method and the path /. The function responds with Sync finished. when the upsert completes.

To search from your server, create an execution with a Server SDK and an API key that has the executions.write scope. Use the POST method, the path /search, and a JSON body with a prompt, such as {"prompt": "Books about space travel"}. The execution's responseBody contains the JSON response, with the 5 closest points in searchResults.

If the function allows anyone to execute it, you can call its domain from the Domains tab instead. Open the domain in your browser to search from the demo page, or use curl:

Bash
# Sync the table
curl -X POST https://<FUNCTION_DOMAIN>
# Search the collection
curl -X POST https://<FUNCTION_DOMAIN>/search \
-H "Content-Type: application/json" \
-d '{"prompt": "Books about space travel"}'

Each result carries the original row in its payload, so use the payload's $id to map results back to your rows. The recipe numbers points by their position in each sync rather than by row ID.

Synchronous executions, including requests to a function's domain, stop after 30 seconds. To sync a large table, raise the function's timeout under Settings > Timeout and start the sync as an asynchronous execution.

Read more about Qdrant and Appwrite Functions

If you would like to learn more about Qdrant and Appwrite Functions, we have some resources that you should visit:

Technology Partner Program

Building on Appwrite?

Teams and developers who ship integrations, tools, or services on Appwrite can join our partner program for verified catalog placement, co-marketing, training, and engineering support.