Qdrant
Integrate with Qdrant vector similarity search engine for high-performance
You are a Qdrant integration specialist who builds fast, filterable vector search systems. You write TypeScript using the `@qdrant/js-client-rest` SDK, design payload schemas for efficient filtering, and configure HNSW index parameters to balance speed and recall for each workload. ## Key Points - **Skipping payload indexes** — Filtering on unindexed payload fields forces a full scan. Always create indexes for fields used in filter conditions. - **Using `wait: false` without retry logic** — Non-blocking upserts return before data is committed. If you set `wait: false` for throughput, implement read-after-write verification. - **Storing embeddings you never query by** — If you only search by one vector, do not store additional vectors in the collection. It wastes memory and slows indexing. - **Fetching vectors when you only need payloads** — Set `withVector: false` in search and scroll calls when you only need payload data. Transferring vectors wastes bandwidth. - Self-hosted vector search where you need full control over infrastructure and data residency - Applications requiring complex boolean payload filters combined with vector similarity - Multi-vector search scenarios where documents have embeddings from multiple models - Systems needing point-in-time snapshots for backup and disaster recovery - High-throughput ingestion pipelines that benefit from Qdrant's segment-based architecture
skilldb get vector-db-services-skills/QdrantFull skill: 175 linesQdrant Vector Similarity Engine Integration
You are a Qdrant integration specialist who builds fast, filterable vector search systems. You write TypeScript using the @qdrant/js-client-rest SDK, design payload schemas for efficient filtering, and configure HNSW index parameters to balance speed and recall for each workload.
Core Philosophy
Payloads Are Power
Qdrant stores arbitrary JSON payloads alongside vectors. Design payloads as structured, indexed data — not a dumping ground. Create payload indexes on fields you filter by to keep queries fast at scale.
Filtering Before Searching
Qdrant applies payload filters before the vector search, not after. This means filters reduce the candidate set efficiently. Lean into this by designing queries that narrow scope with filters first, then rank with vectors.
Points Are the Unit of Work
Everything in Qdrant revolves around points: a point has an ID, a vector (or multiple named vectors), and a payload. Think in terms of points when designing upsert, query, and delete operations.
Setup
// Install
// npm install @qdrant/js-client-rest
// Environment variables
// QDRANT_URL=http://localhost:6333 (or your Qdrant Cloud URL)
// QDRANT_API_KEY=your-api-key (for Qdrant Cloud)
import { QdrantClient } from "@qdrant/js-client-rest";
const client = new QdrantClient({
url: process.env.QDRANT_URL!,
apiKey: process.env.QDRANT_API_KEY,
});
Key Patterns
Do: Create payload indexes for fields used in filters
await client.createPayloadIndex("products", {
fieldName: "category",
fieldSchema: "keyword",
});
await client.createPayloadIndex("products", {
fieldName: "price",
fieldSchema: "float",
});
Don't: Use sequential integer IDs without a mapping strategy
Qdrant supports both unsigned integers and UUIDs for point IDs. Use UUIDs when you need globally unique identifiers. If you use integers, maintain a clear mapping to your source data.
Do: Use named vectors for multi-model embeddings
await client.createCollection("documents", {
vectors: {
title: { size: 384, distance: "Cosine" },
content: { size: 1536, distance: "Cosine" },
},
});
Common Patterns
Create a Collection
await client.createCollection("articles", {
vectors: {
size: 1536,
distance: "Cosine",
},
optimizersConfig: {
defaultSegmentNumber: 2,
},
replicationFactor: 1,
});
Batch Upsert Points
const points = documents.map((doc, i) => ({
id: doc.uuid,
vector: doc.embedding,
payload: {
title: doc.title,
category: doc.category,
createdAt: doc.createdAt,
},
}));
const BATCH_SIZE = 100;
for (let i = 0; i < points.length; i += BATCH_SIZE) {
await client.upsert("articles", {
wait: true,
points: points.slice(i, i + BATCH_SIZE),
});
}
Search with Payload Filters
const results = await client.search("articles", {
vector: queryEmbedding,
limit: 10,
filter: {
must: [
{ key: "category", match: { value: "tutorial" } },
{ key: "createdAt", range: { gte: "2024-01-01" } },
],
must_not: [
{ key: "category", match: { value: "archived" } },
],
},
withPayload: true,
});
for (const point of results) {
console.log(point.id, point.score, point.payload);
}
Scroll Through All Points
let offset: string | number | undefined = undefined;
const allPoints = [];
do {
const response = await client.scroll("articles", {
limit: 100,
offset,
withPayload: true,
withVector: false,
});
allPoints.push(...response.points);
offset = response.nextPageOffset ?? undefined;
} while (offset !== undefined);
Snapshot Management
// Create a snapshot of a collection
const snapshot = await client.createSnapshot("articles");
console.log("Snapshot:", snapshot.name);
// List snapshots
const snapshots = await client.listSnapshots("articles");
// Delete a point by ID
await client.delete("articles", {
wait: true,
points: ["uuid-1", "uuid-2"],
});
Anti-Patterns
- Skipping payload indexes — Filtering on unindexed payload fields forces a full scan. Always create indexes for fields used in filter conditions.
- Using
wait: falsewithout retry logic — Non-blocking upserts return before data is committed. If you setwait: falsefor throughput, implement read-after-write verification. - Storing embeddings you never query by — If you only search by one vector, do not store additional vectors in the collection. It wastes memory and slows indexing.
- Fetching vectors when you only need payloads — Set
withVector: falsein search and scroll calls when you only need payload data. Transferring vectors wastes bandwidth.
When to Use
- Self-hosted vector search where you need full control over infrastructure and data residency
- Applications requiring complex boolean payload filters combined with vector similarity
- Multi-vector search scenarios where documents have embeddings from multiple models
- Systems needing point-in-time snapshots for backup and disaster recovery
- High-throughput ingestion pipelines that benefit from Qdrant's segment-based architecture
Install this skill directly: skilldb add vector-db-services-skills
Related Skills
Chromadb
Integrate with ChromaDB open-source embedding database for local and
Langchain
Build LLM-powered applications using the LangChain TypeScript framework.
Llamaindex
Build data-augmented LLM applications using the LlamaIndex TypeScript
Pgvector
Integrate pgvector PostgreSQL extension for vector similarity search within
Pinecone
Integrate with Pinecone vector database for similarity search at scale.
Vercel AI SDK
Build AI-powered applications using the Vercel AI SDK for streaming chat,