mcpField
A
api-vector-db-qdrant

api-vector-db-qdrant

github.com/agents-inc数据与数据库2653 次安装2 天前更新
代码仓库

关于 api-vector-db-qdrant

面向使用 Qdrant JavaScript 客户端进行向量搜索的开发者,涵盖集合配置、负载过滤、命名向量、推荐查询与量化。

主要功能

  1. 01集合与向量配置
  2. 02点的写入、查询和删除
  3. 03负载过滤与索引
  4. 04每个点存储多个命名向量
  5. 05推荐查询
  6. 06量化选项

适用场景

  1. 01构建文档语义检索
  2. 02按元数据筛选相似度搜索
  3. 03根据正反示例生成推荐
  4. 04通过量化减少向量内存占用

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agents-inc/skills --skill api-vector-db-qdrant

安装后在 Claude Code 中输入/api-vector-db-qdrant确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

metadata.yaml
reference.md
examples/
core.md
filtering.md
named-vectors-quantization.md
recommendations-batch.md

详细介绍

Qdrant 模式

快速指南: 使用 @qdrant/js-client-rest(v1.17.x)进行高性能向量搜索。集合会预先定义向量维度和距离度量——不匹配会导致无提示的失败。使用带有载荷条件的 must/should/must_not 过滤子句(而不是 Pinecone 风格的 $eq/$and)。载荷索引是可选的,但对于大规模场景下的过滤性能至关重要——请使用 createPayloadIndex() 显式创建。命名向量可让你在每个点中存储多个嵌入(例如标题 + 内容)。量化(标量/二进制/乘积)以准确度换取内存和速度。query() 方法是通用搜索端点——优先使用它,而不是较旧的 search() 方法。


<critical_requirements>

重要:使用此技能前

(对于过滤器中使用的任何字段,你都必须使用 createPayloadIndex() 创建载荷索引——未建立索引的字段会触发全量扫描,性能会随集合大小线性下降。)

(你必须使用 must/should/must_not 过滤语法——Qdrant 不使用 Pinecone 中的 $eq/$and/$or 运算符。)

(嵌入模型的输出维度必须与你的集合配置完全一致——维度不匹配会导致 upsert 无提示地失败,或搜索结果损坏。)

(如果后续读取依赖写入的数据,你必须在写入时设置 wait: true——Qdrant 默认异步写入,数据可能不会立即可见。)

</critical_requirements>


示例

  • 核心模式 -- 客户端设置、集合创建、upsert、查询、滚动、删除
  • 过滤 -- must/should/must_not 条件、匹配/范围运算符、载荷索引
  • 命名向量与量化 -- 每个点中的多个向量、标量/二进制/乘积量化
  • 推荐与批处理 -- 推荐 API、批量操作、快照

其他资源:

  • reference.md -- API 快速参考、过滤运算符、限制、决策框架、生产环境检查清单

自动检测: Qdrant、QdrantClient、@qdrant/js-client-rest、createCollection、upsert、query、scroll、recommend、setPayload、createPayloadIndex、must、should、must_not、载荷、命名向量、量化、向量数据库、相似性搜索、语义搜索、RAG 检索、嵌入搜索

适用场景:

  • 对文档嵌入进行语义搜索(RAG 检索流水线)
  • 用于推荐、去重或分类的相似性搜索
  • 使用命名向量进行多向量搜索(例如,每篇文档分别包含标题嵌入和内容嵌入)
  • 使用复杂载荷条件(must/should/must_not)进行过滤式向量搜索
  • 使用标量、二进制或乘积量化的内存优化型部署

涵盖的关键模式:

  • 客户端设置与集合管理(距离度量、HNSW 配置)
  • 点的 CRUD 操作(upsert、查询、滚动、检索、删除、计数)
  • 使用 must/should/must_not 和匹配/范围条件进行载荷过滤
  • 使用命名向量存储每个点的多个嵌入
  • 量化配置(标量、二进制、乘积)
  • 使用正面/负面示例的推荐 API
  • 批量操作与快照管理
  • 用于提升过滤性能的载荷索引

不适用场景:

  • 使用 BM25 排名的全文搜索(请使用专用搜索引擎)
  • 带有联接和事务的关系型数据(请使用关系型数据库)
  • 不涉及向量相似性的键值查找(请使用 KV 存储)
  • 存储大型文档或二进制数据块(仅存储嵌入和元数据引用)

## 理念

Qdrant 是一个用 Rust 构建的高性能开源向量数据库,专为大规模过滤相似性搜索而设计。核心原则:存储带有丰富负载的向量,按相似性搜索,按负载条件筛选。

核心原则:

  1. 负载是一等公民——与将元数据视为次要信息的数据库不同,Qdrant 的负载系统支持复杂的嵌套 JSON、多种数据类型和精细的索引。使用负载进行筛选,而不只是注释。
  2. 为筛选字段创建索引——负载索引不会自动创建。通过 createPayloadIndex() 为筛选中使用的字段显式创建索引。没有索引时,筛选会导致扫描整个集合。
  3. 使用命名向量处理多模态数据——单个点可以保存多个命名向量(例如,标题嵌入和内容嵌入)。搜索时需要指定目标命名向量。这样可以避免在多个集合中重复存储负载。
  4. 通过量化实现规模化——标量量化(压缩 4 倍)、二进制量化(压缩 32 倍)和乘积量化以精度换取内存节省。可在集合级别或向量级别配置。使用 always_ram: true 将量化向量保留在内存中以提升速度。
  5. 写入默认是异步的——Upsert 会在数据持久化到所有副本之前返回。需要即时一致性时(例如,读后写流程),设置 wait: true。

核心模式

模式 1:客户端初始化

创建连接到本地实例或 Qdrant Cloud 的 QdrantClient。完整示例请参阅 examples/core.md。

// Good Example
import { QdrantClient } from "@qdrant/js-client-rest";

function createQdrantClient(): QdrantClient {
  const url = process.env.QDRANT_URL;
  const apiKey = process.env.QDRANT_API_KEY;
  if (!url) {
    throw new Error("QDRANT_URL environment variable is required");
  }
  return new QdrantClient({ url, apiKey });
}

export { createQdrantClient };

优点: 从环境变量读取 URL 和 API 密钥,构造前进行验证,使用具名导出

// Bad Example
import { QdrantClient } from "@qdrant/js-client-rest";
const client = new QdrantClient({
  host: "my-cluster.cloud.qdrant.io",
  apiKey: "sk-abc123...",
});
// Hardcoded credentials leak in version control

缺点: API 密钥硬编码,主机未使用 HTTPS(连接云端时应使用带完整协议的 url)


模式 2:创建集合

定义向量维度和距离度量。维度必须与嵌入模型的输出完全一致。请参阅 examples/core.md。

// Good Example
const EMBEDDING_DIMENSION = 1536;

await client.createCollection("documents", {
  vectors: {
    size: EMBEDDING_DIMENSION,
    distance: "Cosine",
  },
});

export { EMBEDDING_DIMENSION };

优点: 使用具名常量定义维度,显式指定距离度量,配置简洁

// Bad Example
await client.createCollection("documents", {
  vectors: { size: 768, distance: "Cosine" },
  // Dimension mismatch if using a 1536-dim model -- upserts may silently fail or produce garbage search results
});

缺点: 维度硬编码,可能与嵌入模型不匹配;未使用具名常量


模式 3:Upsert 带负载的点

Upsert 带负载(Qdrant 对元数据的称呼)的向量。请参阅 examples/core.md。

// Good Example
interface DocumentPayload {
  title: string;
  category: string;
  createdAt: number;
  tags: string[];
}

await client.upsert("documents", {
  wait: true,
  points: [
    {
      id: "doc-1",
      vector: embedding,
      payload: {
        title: "Guide",
        category: "tutorial",
        createdAt: 1710000000,
        tags: ["ai", "search"],
      },
    },
  ],
});

优点: 使用类型化负载接口,通过 wait: true 实现即时一致性,负载结构清晰


模式 4:使用负载过滤器查询

使用 must/should/must_not 过滤子句——不要使用 Pinecone 风格的 $eq/$and。请参阅 examples/filtering.md。

// Good Example
const TOP_K = 10;

const results = await client.query("documents", {
  query: queryEmbedding,
  filter: {
    must: [
      { key: "category", match: { value: "tutorial" } },
      { key: "createdAt", range: { gte: 1700000000 } },
    ],
  },
  with_payload: true,
  limit: TOP_K,
});

for (const point of results.points) {
  console.log(point.id, point.score, point.payload);
}

优点: 使用具名常量定义限制数量,采用 Qdrant 过滤语法(must + match/range),包含 with_payload

// Bad Example -- Pinecone syntax does NOT work in Qdrant
const results = await client.query("documents", {
  query: embedding,
  filter: {
    $and: [{ category: { $eq: "tutorial" } }],
  },
  limit: 100,
});

缺点: Pinecone 风格的 $and/$eq 运算符在 Qdrant 中无效,限制数量使用了魔法数字


模式 5:命名向量

为每个点存储多个嵌入。请参阅 examples/named-vectors-quantization.md。

// Good Example
const TITLE_DIM = 384;
const CONTENT_DIM = 1536;

await client.createCollection("articles", {
  vectors: {
    title: { size: TITLE_DIM, distance: "Cosine" },
    content: { size: CONTENT_DIM, distance: "Cosine" },
  },
});

// Upsert with named vectors
await client.upsert("articles", {
  wait: true,
  points: [
    {
      id: "article-1",
      vector: { title: titleEmbedding, content: contentEmbedding },
      payload: { title: "Intro to Vectors" },
    },
  ],
});

// Search by specific named vector
const results = await client.query("articles", {
  query: queryEmbedding,
  using: "content",
  limit: TOP_K,
});

优点: 不同命名向量可使用不同维度,using 指定要搜索的向量,避免在多个集合中重复存储负载


模式 6:推荐 API

使用正面/负面示例查找相似点。请参阅 examples/recommendations-batch.md。

// Good Example
const results = await client.query("documents", {
  query: {
    recommend: {
      positive: [1, 42],
      negative: [7],
      strategy: "best_score",
    },
  },
  limit: TOP_K,
  with_payload: true,
});

优点: 使用点 ID 作为正面/负面示例,best_score 策略处理负面示例的效果优于默认的 average_vector


<decision_framework>

决策框架

选择哪种距离度量?
Which distance metric should I use?
|-- Using normalized embeddings (OpenAI, Cohere)? -> Cosine (most common, safe default)
|-- Pre-normalized embeddings and need speed? -> Dot (faster, same results as Cosine for unit vectors)
|-- Raw feature vectors where magnitude matters? -> Euclid (L2 distance)
|-- City-block distance needed? -> Manhattan
'-- Unsure? -> Cosine (works with any embedding model)
使用单个向量还是命名向量?
How many embeddings per point?
|-- One embedding model? -> Single vector (simpler config)
|-- Multiple embedding models (title + content)? -> Named vectors
|-- Same model, different text segments? -> Named vectors
|-- Multi-modal (text + image)? -> Named vectors with different dimensions
'-- Want to avoid duplicating payloads across collections? -> Named vectors
选择哪种量化方法?
How should I optimize memory?
|-- Good default, balanced accuracy/speed? -> Scalar (int8, 4x compression)
|-- Maximum speed, can tolerate accuracy loss? -> Binary (32x compression)
|   '-- Best with high-dimensional models (>= 1024 dims)
|-- Maximum compression, speed not critical? -> Product (up to 64x compression)
|   '-- Slowest quantization, most accuracy loss
'-- No memory pressure? -> Skip quantization (full float32 precision)
如何制定负载索引策略?
Should I create a payload index?
|-- Field used in filter conditions? -> YES, always index
|-- Field used in order_by for scroll? -> YES, index for sort performance
|-- Field only read after search (display only)? -> NO, skip index
|-- High-cardinality field (UUIDs, timestamps)? -> YES, but evaluate index type
'-- Low-cardinality field (enum-like)? -> YES, keyword index is very efficient

</decision_framework>


<red_flags>

风险信号

高优先级问题:

  • 使用 Pinecone 风格的过滤器语法($eq、$and、$or)——Qdrant 使用 must/should/must_not 搭配 match/range 条件
  • 嵌入模型与集合配置的向量维度不匹配——会导致静默失败或产生无用结果
  • 未为过滤字段创建载荷索引——会导致扫描整个集合,且性能会随集合大小线性下降
  • 需要读后写一致性时未设置 wait: true——写入默认是异步的

中优先级问题:

  • 使用已弃用的 search() 方法,而不是 query()——query() 是通用端点,支持预取和融合
  • 查询时忘记设置 with_payload: true——默认不会包含载荷
  • 批量 upsert 后才创建载荷索引,而不是提前创建——事后建索引比在 upsert 期间建索引更慢
  • 在滚动查询中使用 offset 进行深度分页——性能会下降;应将 offset 用作游标(点 ID),而不是页码

常见错误:

  • 在错误的嵌套层级传入 filter——filter 应放在查询参数的顶层,而不是嵌套在另一个对象中
  • 使用 id: 0 作为点 ID——Qdrant 要求使用正整数或 UUID 字符串;0 无效
  • 混淆 setPayload(合并)与 overwritePayload(替换)——setPayload 会合并字段,overwritePayload 会替换整个载荷
  • 调用 deletePayload 时只传入字段名,却未指定点选择器——必须通过 points 数组或 filter 指定要更新的点

注意事项和边界情况:

  • 点 ID 必须是正整数或 UUID 字符串——负数、0 和非 UUID 字符串都会被拒绝
  • 使用 order_by 的 scroll() 要求排序字段已创建载荷索引——否则请求会失败
  • 对大型集合使用 exact: true 的 count() 会很慢——应使用 exact: false(默认值)获取近似计数
  • 快照恢复要求 Qdrant 的次版本号一致——v1.14.x 快照无法恢复到 v1.15.x 集群
  • 二值量化最适合高维向量(>= 1024 dims)——对于较小的向量,标量量化更准确
  • 使用 prefetch 的 query() 可启用多阶段检索(先检索 1000 个,再重新排序并取前 10 个)——但需要了解预取流程
  • 命名向量搜索需要 using 参数——省略该参数会搜索默认的(未命名)向量,而该向量可能不存在
  • deletePayload 会移除指定键,clearPayload 会移除所有键——这是两种不同的操作

</red_flags>


<critical_reminders>

关键提醒

(对于过滤器中使用的任何字段,必须使用 createPayloadIndex() 创建载荷索引——未建立索引的字段会导致扫描整个集合,且性能会随集合大小线性下降)

(必须使用 must/should/must_not 过滤器语法——Qdrant 不使用 Pinecone 那样的 $eq/$and/$or 运算符)

(必须确保嵌入模型输出与集合配置的向量维度完全一致——维度不匹配会导致 upsert 静默失败或搜索结果损坏)

(如果后续读取依赖写入的数据,必须在写入时设置 wait: true——Qdrant 的写入默认是异步的,数据可能不会立即可见)

不遵循这些规则会导致搜索结果为空、过滤性能下降、数据一致性问题,以及难以排查的维度不匹配错误。

</critical_reminders>

评论

支持 Markdown