npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@memberjunction/ai-vectors-qdrant

v5.24.0

Published

MemberJunction: Qdrant Implementation for AI Vector Database

Readme

@memberjunction/ai-vectors-qdrant

MemberJunction vector database provider backed by Qdrant. Implements the VectorDBBase interface using the official @qdrant/js-client-rest client.

Prerequisites

  • A running Qdrant instance (local Docker container or Qdrant Cloud cluster)
  • For Qdrant Cloud, an API key with appropriate permissions

Installation

npm install @memberjunction/ai-vectors-qdrant

How It Works

Each logical "index" maps to a Qdrant collection. A collection stores points, where each point consists of:

| Component | Description | |---|---| | ID | A string or integer identifier for the point | | Vector | The embedding (dimension and distance metric are fixed at collection creation) | | Payload | Arbitrary JSON key-value metadata stored alongside the vector |

When you call CreateIndex, the provider creates a Qdrant collection with the specified vector size and distance metric. You can pass additional Qdrant-specific collection parameters (e.g., HNSW config, quantization) via params.additionalParams.

Records are upserted via the Qdrant upsert operation, so calling CreateRecord or CreateRecords with an existing ID overwrites the previous point.

Queries use Qdrant's native ANN search. When a vector is provided, the provider calls query() directly. When only a point id is provided, the provider first retrieves that point's vector, then uses it as the query vector.

DeleteAllRecords works by deleting and recreating the collection with the same vector configuration, since Qdrant does not expose a single "truncate" operation.

Supported Distance Metrics

| MJ Metric Value | Qdrant Distance | Description | |---|---|---| | cosine (default) | Cosine | Cosine similarity (normalized dot product) | | euclidean | Euclid | Euclidean (L2) distance | | dotproduct | Dot | Dot product (inner product) |

The distance metric is set at collection creation time and cannot be changed afterward.

Configuration

Environment Variables

| Variable | Default | Description | |---|---|---| | QDRANT_URL | http://localhost:6333 | Qdrant server URL. For Qdrant Cloud, use the full cluster URL (e.g., https://xyz.us-east-1-0.aws.cloud.qdrant.io:6333). | | QDRANT_API_KEY | (none) | API key for authentication. Required for Qdrant Cloud; optional for local instances. |

Constructor

The apiKey constructor parameter is passed directly to the Qdrant client. If empty or 'default', no API key header is sent (suitable for local instances):

// Local instance (no auth)
const db = new QdrantDatabase('default');

// Qdrant Cloud
const db = new QdrantDatabase(process.env.QDRANT_API_KEY);

Usage

import { QdrantDatabase } from '@memberjunction/ai-vectors-qdrant';

const db = new QdrantDatabase(process.env.QDRANT_API_KEY || 'default');

// Create a collection
await db.CreateIndex({
    id: 'my-collection',
    dimension: 1536,
    metric: 'cosine',
});

// Upsert records
await db.CreateRecords([
    {
        id: 'vec-1',
        values: [0.1, 0.2, ...],
        metadata: { Entity: 'Documents', RecordID: '123' },
    },
    {
        id: 'vec-2',
        values: [0.3, 0.4, ...],
        metadata: { Entity: 'Documents', RecordID: '456' },
    },
], 'my-collection');

// Query by vector similarity
const results = await db.QueryIndex({
    id: 'my-collection',
    vector: [0.1, 0.2, ...],
    topK: 10,
    includeMetadata: true,
});

// List all collections
const indexes = await db.ListIndexes();

// Get collection details (dimension, metric)
const info = await db.GetIndex({ id: 'my-collection' });

// Delete specific records
await db.DeleteRecords(
    [{ id: 'vec-1', values: [] }],
    'my-collection'
);

// Delete all records (drops and recreates the collection)
await db.DeleteAllRecords('my-collection');

// Delete the collection entirely
await db.DeleteIndex({ id: 'my-collection' });

Metadata Filtering

Qdrant uses a structured filter format with must, should, and must_not clauses. This provider supports two approaches for building filters.

SharedIndexFilterOptions (Cross-Provider)

The recommended approach uses BuildMetadataFilter(), which accepts the provider-agnostic SharedIndexFilterOptions interface and produces a Qdrant-native filter:

const filter = db.BuildMetadataFilter({
    EntityName: 'Documents',
    RecordIDs: ['rec-1', 'rec-2'],
});

const results = await db.QueryIndex({
    id: 'my-collection',
    vector: [...],
    topK: 10,
    filter,
});

Under the hood, BuildMetadataFilter performs the following mapping:

| SharedIndexFilterOptions field | Qdrant filter clause | |---|---| | EntityName | must: [{ key: "Entity", match: { value: "Documents" } }] | | RecordIDs (single value) | must: [{ key: "RecordID", match: { value: "rec-1" } }] | | RecordIDs (multiple values) | must: [{ key: "RecordID", match: { any: ["rec-1", "rec-2"] } }] | | Additional conditions via VectorMetadataFilter.BuildConditions | Mapped with eq -> match.value, in -> match.any, contains -> match.value |

All conditions are combined into a single must array (AND logic).

Qdrant-Native Filters

You can also pass Qdrant's native filter syntax directly as the filter property on QueryIndex:

const results = await db.QueryIndex({
    id: 'my-collection',
    vector: [...],
    topK: 10,
    filter: {
        must: [
            { key: 'category', match: { value: 'science' } },
            { key: 'year', range: { gte: 2020 } },
        ],
        must_not: [
            { key: 'status', match: { value: 'archived' } },
        ],
    },
});

This gives you full access to Qdrant's filtering capabilities including range filters, geo filters, and nested conditions. See the Qdrant filtering documentation for the complete filter syntax.

Record Operations

GetRecord / GetRecords

To retrieve points by ID, pass the collection name in params.data:

const result = await db.GetRecords({
    id: 'ignored',
    data: {
        collectionName: 'my-collection',
        ids: ['vec-1', 'vec-2'],
    },
});

UpdateRecord / UpdateRecords

Updates use upsert for records with vectors and setPayload for metadata-only updates:

await db.UpdateRecord({
    id: 'vec-1',
    values: [0.5, 0.6, ...],       // new vector (uses upsert)
    metadata: { status: 'updated' },
    data: { collectionName: 'my-collection' },
});

// Metadata-only update (no vector change)
await db.UpdateRecord({
    id: 'vec-1',
    metadata: { status: 'reviewed' },
    data: { collectionName: 'my-collection' },
});

EditIndex

Qdrant supports updating collection-level parameters (optimizer settings, etc.) via EditIndex:

await db.EditIndex({
    id: 'my-collection',
    data: {
        optimizers_config: {
            indexing_threshold: 20000,
        },
    },
});

Limitations

  • No hybrid search: The SupportsHybridSearch property is not overridden and defaults to the base class behavior. Pure vector search only.
  • ListIndexes dimension/metric: The ListIndexes method returns dimension: 0 and metric: 'cosine' for all collections because the Qdrant list endpoint does not return per-collection vector configuration. Use GetIndex for accurate details.
  • DeleteAllRecords is destructive: The collection is dropped and recreated, which resets all optimizer and indexing state.
  • String IDs only: While Qdrant supports both string and integer point IDs, the MJ interface uses string IDs throughout. Integer IDs are converted to strings in results.
  • Single vector per point: Named vector configurations are not currently exposed; only the default (unnamed) vector is used.
  • No namespace support: Qdrant does not have a namespace concept. The namespace parameter on DeleteAllRecords is ignored.