Installation
Install via npm:npm install @qdrant/js-client-rest
yarn add @qdrant/js-client-rest
Quick Start
import { QdrantClient } from '@qdrant/js-client-rest';
const client = new QdrantClient({ url: 'http://localhost:6333' });
// Create collection
await client.createCollection('my_collection', {
vectors: {
size: 384,
distance: 'Cosine',
},
});
// Upsert points
await client.upsert('my_collection', {
points: [
{
id: 1,
vector: [0.05, 0.61, 0.76, 0.74],
payload: { city: 'Berlin', country: 'Germany' },
},
{
id: 2,
vector: [0.19, 0.81, 0.75, 0.11],
payload: { city: 'London', country: 'UK' },
},
],
});
// Search
const results = await client.search('my_collection', {
vector: [0.2, 0.1, 0.9, 0.7],
limit: 3,
});
console.log(results);
Repository
GitHub Repository
Official JavaScript client:
qdrant/qdrant-jsClient Initialization
Basic Connection
import { QdrantClient } from '@qdrant/js-client-rest';
// Connect to local instance
const client = new QdrantClient({
url: 'http://localhost:6333',
});
// Connect to Qdrant Cloud
const cloudClient = new QdrantClient({
url: 'https://your-cluster.cloud.qdrant.io',
apiKey: 'your-api-key',
});
With Custom Options
const client = new QdrantClient({
url: 'http://localhost:6333',
apiKey: 'your-api-key',
timeout: 30000, // Request timeout in ms
headers: {
'Custom-Header': 'value',
},
});
TypeScript Support
The client has full TypeScript definitions:import { QdrantClient, Schemas } from '@qdrant/js-client-rest';
type PointPayload = {
title: string;
category: string;
views: number;
tags: string[];
};
const client = new QdrantClient({ url: 'http://localhost:6333' });
// Type-safe point structure
const point: Schemas['PointStruct'] = {
id: 1,
vector: [0.1, 0.2, 0.3],
payload: {
title: 'Document 1',
category: 'technology',
views: 1500,
tags: ['ai', 'ml'],
} as PointPayload,
};
await client.upsert('my_collection', {
points: [point],
});
// Type-safe search results
const results = await client.search('my_collection', {
vector: [0.2, 0.1, 0.9],
limit: 10,
});
results.forEach((result) => {
console.log(result.id);
console.log(result.score);
const payload = result.payload as PointPayload;
console.log(payload.title);
});
Collection Management
Create Collection
// Single vector
await client.createCollection('my_collection', {
vectors: {
size: 768,
distance: 'Cosine',
on_disk: false,
},
});
// Multiple named vectors
await client.createCollection('multi_vector', {
vectors: {
text: {
size: 768,
distance: 'Cosine',
},
image: {
size: 512,
distance: 'Euclid',
},
},
});
Create with HNSW Config
await client.createCollection('optimized', {
vectors: {
size: 384,
distance: 'Cosine',
hnsw_config: {
m: 16,
ef_construct: 100,
full_scan_threshold: 10000,
},
},
optimizers_config: {
default_segment_number: 2,
indexing_threshold: 50000,
},
replication_factor: 2,
write_consistency_factor: 1,
});
Get Collection Info
const info = await client.getCollection('my_collection');
console.log(`Status: ${info.status}`);
console.log(`Vectors count: ${info.vectors_count}`);
console.log(`Points count: ${info.points_count}`);
console.log(`Segments: ${info.segments_count}`);
List Collections
const collections = await client.getCollections();
collections.collections.forEach((collection) => {
console.log(collection.name);
});
Update Collection
await client.updateCollection('my_collection', {
optimizers_config: {
indexing_threshold: 50000,
memmap_threshold: 100000,
},
});
Delete Collection
await client.deleteCollection('my_collection');
Point Operations
Upsert Points
import { v4 as uuidv4 } from 'uuid';
await client.upsert('my_collection', {
points: [
{
id: uuidv4(), // UUID string
vector: [0.05, 0.61, 0.76, 0.74],
payload: {
title: 'Document 1',
category: 'technology',
views: 1500,
tags: ['ai', 'ml', 'vector-db'],
},
},
{
id: 2, // Integer ID
vector: [0.19, 0.81, 0.75, 0.11],
payload: { title: 'Document 2' },
},
],
wait: true, // Wait for operation to complete
});
Batch Upsert
const batchSize = 100;
const totalPoints = 10000;
for (let i = 0; i < totalPoints; i += batchSize) {
const points = Array.from({ length: batchSize }, (_, j) => ({
id: i + j,
vector: Array.from({ length: 384 }, () => Math.random()),
payload: { index: i + j },
}));
await client.upsert('my_collection', {
points,
wait: false, // Don't wait for faster throughput
});
}
Get Points
const points = await client.retrieve('my_collection', {
ids: [1, 2, 3],
with_payload: true,
with_vector: true,
});
points.forEach((point) => {
console.log(`ID: ${point.id}`);
console.log(`Vector: ${point.vector}`);
console.log(`Payload:`, point.payload);
});
Delete Points
// Delete by IDs
await client.delete('my_collection', {
points: [1, 2, 3],
});
// Delete by filter
await client.delete('my_collection', {
filter: {
must: [
{
key: 'category',
match: { value: 'outdated' },
},
],
},
});
Search Operations
Basic Search
const results = await client.search('my_collection', {
vector: [0.2, 0.1, 0.9, 0.7],
limit: 10,
with_payload: true,
with_vector: false,
});
results.forEach((result) => {
console.log(result.id, result.score);
console.log(result.payload);
});
Search with Filtering
const results = await client.search('my_collection', {
vector: [0.2, 0.1, 0.9, 0.7],
filter: {
must: [
{
key: 'category',
match: { value: 'technology' },
},
{
key: 'views',
range: {
gte: 1000,
lt: 10000,
},
},
],
},
limit: 5,
score_threshold: 0.7,
});
Search with Parameters
const results = await client.search('my_collection', {
vector: [0.2, 0.1, 0.9, 0.7],
limit: 20,
params: {
hnsw_ef: 128, // Higher ef for better recall
exact: false, // Use approximate search
quantization: {
ignore: false,
rescore: true,
oversampling: 2.0,
},
},
});
Batch Search
const results = await client.searchBatch('my_collection', {
searches: [
{
vector: [0.2, 0.1, 0.9, 0.7],
limit: 5,
filter: {
must: [{ key: 'category', match: { value: 'tech' } }],
},
},
{
vector: [0.5, 0.3, 0.2, 0.8],
limit: 10,
},
],
});
results.forEach((batch, index) => {
console.log(`Results for query ${index}:`);
batch.forEach((point) => console.log(point.id, point.score));
});
Recommendations
Basic Recommendations
const results = await client.recommend('my_collection', {
positive: [1, 2, 3], // Point IDs to use as positive examples
negative: [10], // Point IDs to avoid
limit: 10,
});
Recommend with Strategy
const results = await client.recommend('my_collection', {
positive: [1, 2],
negative: [10],
strategy: 'best_score', // or 'average_vector'
limit: 5,
filter: {
must: [{ key: 'category', match: { value: 'tech' } }],
},
});
Batch Recommendations
const results = await client.recommendBatch('my_collection', {
searches: [
{
positive: [1, 2],
negative: [10],
limit: 5,
},
{
positive: [3, 4, 5],
limit: 10,
},
],
});
Query API (Universal)
// Hybrid search with fusion
const results = await client.query('my_collection', {
prefetch: [
{
query: [0.1, 0.2, 0.3], // Dense vector
using: 'dense',
limit: 100,
},
{
query: { indices: [1, 5, 10], values: [0.5, 0.3, 0.2] }, // Sparse vector
using: 'sparse',
limit: 100,
},
],
query: { fusion: 'rrf' }, // Reciprocal Rank Fusion
limit: 10,
});
Payload Operations
Set Payload
await client.setPayload('my_collection', {
payload: {
new_field: 'value',
updated_at: '2024-01-01',
},
points: [1, 2, 3],
});
Overwrite Payload
await client.overwritePayload('my_collection', {
payload: { only_field: 'value' },
points: [1, 2],
});
Delete Payload Keys
await client.deletePayload('my_collection', {
keys: ['old_field', 'deprecated'],
points: [1, 2, 3],
});
Clear Payload
await client.clearPayload('my_collection', {
points: [1, 2, 3],
});
Scroll (Pagination)
let offset: string | number | null = null;
const allPoints = [];
while (true) {
const result = await client.scroll('my_collection', {
limit: 100,
offset: offset || undefined,
with_payload: true,
filter: {
must: [{ key: 'category', match: { value: 'tech' } }],
},
});
allPoints.push(...result.points);
offset = result.next_page_offset;
if (!offset) break;
}
console.log(`Total points: ${allPoints.length}`);
Payload Indexing
// Create keyword index
await client.createPayloadIndex('my_collection', {
field_name: 'category',
field_schema: 'keyword',
});
// Create text index for full-text search
await client.createPayloadIndex('my_collection', {
field_name: 'description',
field_schema: {
type: 'text',
tokenizer: 'word',
lowercase: true,
min_token_len: 2,
max_token_len: 20,
},
});
// Delete index
await client.deletePayloadIndex('my_collection', 'category');
Snapshots
Create Snapshot
const snapshot = await client.createSnapshot('my_collection');
console.log(`Snapshot name: ${snapshot.name}`);
List Snapshots
const snapshots = await client.listSnapshots('my_collection');
snapshots.forEach((snapshot) => {
console.log(snapshot.name);
});
Recover from Snapshot
await client.recoverSnapshot('my_collection', {
location: 'http://localhost:6333/snapshots/my_collection/snapshot.snapshot',
});
Error Handling
import { QdrantClient } from '@qdrant/js-client-rest';
const client = new QdrantClient({ url: 'http://localhost:6333' });
try {
await client.getCollection('nonexistent');
} catch (error: any) {
if (error.status === 404) {
console.log('Collection not found');
} else {
console.error(`Error: ${error.status} - ${error.message}`);
}
}
Usage with Node.js
const { QdrantClient } = require('@qdrant/js-client-rest');
const client = new QdrantClient({ url: 'http://localhost:6333' });
async function main() {
// Create collection
await client.createCollection('my_collection', {
vectors: {
size: 384,
distance: 'Cosine',
},
});
// Upsert points
await client.upsert('my_collection', {
points: [
{
id: 1,
vector: [0.05, 0.61, 0.76, 0.74],
payload: { name: 'Document 1' },
},
],
});
// Search
const results = await client.search('my_collection', {
vector: [0.2, 0.1, 0.9, 0.7],
limit: 5,
});
console.log(results);
}
main().catch(console.error);
Usage with Browser
<!DOCTYPE html>
<html>
<head>
<script type="module">
import { QdrantClient } from 'https://cdn.jsdelivr.net/npm/@qdrant/js-client-rest/+esm';
const client = new QdrantClient({
url: 'http://localhost:6333',
});
async function search() {
const results = await client.search('my_collection', {
vector: [0.2, 0.1, 0.9, 0.7],
limit: 5,
});
console.log(results);
}
search();
</script>
</head>
<body>
<h1>Qdrant Browser Example</h1>
</body>
</html>
Advanced Filtering
// Complex filter with nested conditions
const results = await client.search('my_collection', {
vector: [0.2, 0.1, 0.9],
filter: {
must: [
{
key: 'category',
match: { value: 'technology' },
},
],
should: [
{
key: 'views',
range: { gte: 10000 },
},
{
key: 'featured',
match: { value: true },
},
],
must_not: [
{
key: 'status',
match: { value: 'archived' },
},
],
},
limit: 10,
});
Best Practices
Performance tips:
- Use batch operations for multiple points
- Set
wait: falsefor faster upserts - Create payload indexes before filtering
- Use appropriate batch sizes (100-1000 points)
Common issues:
- Always handle errors with try-catch
- Ensure vector dimensions match collection config
- Use UUID strings or integers for point IDs
- Handle pagination when scrolling large datasets
Next Steps
Python Client
Python client documentation
Rust Client
Rust client library