搞定了核心概念,接下来看实战。本文带你从 Docker 一键拉起 Qdrant 开始,逐一拆解距离度量、向量维度、量化开关、分片与副本等关键配置项,最后用 Python SDK 完成一套完整的 CRUD + 搜索 + 过滤流程,建议收藏对照操作。
一、Docker 一键拉起 Qdrant,打开 Web 可视化面板
1.1 Docker 快速启动
一行命令即可在本地启动 Qdrant:
docker run -d \ --name qdrant \ -p 6333:6333 \ -v $(pwd)/qdrant_storage:/qdrant/storage \ qdrant/qdrant:latest
参数说明:
| |
|---|
-d | |
--name qdrant | |
-p 6333:6333 | |
-v ... | |
1.2 打开 Web 可视化面板
浏览器访问 http://localhost:6333/dashboard,即可看到 Qdrant 自带的管理界面。
这个面板可以:
- • ✅ 查看所有集合(Collections)列表及状态
💡 生产级部署建议:挂载快照目录 + 自定义配置文件,并设置 API Key。
docker run -d \ --name qdrant \ -p 6333:6333 \ -p 6334:6334 \ -v $(pwd)/qdrant_storage:/qdrant/storage \ -v $(pwd)/snapshots:/qdrant/snapshots \ -v $(pwd)/config.yaml:/qdrant/config/production.yaml \ qdrant/qdrant:latest
二、距离度量方式:4种选择,怎么选?
Qdrant 支持 4 种距离度量方式,创建集合时必须指定。选对了影响检索质量。
2.1 Cosine(余弦相似度)—— 文本嵌入首选
衡量两个向量在方向上的夹角余弦值,越接近 1 越相似。
from qdrant_client.http import modelsvectors_config = models.VectorParams( size=768, distance=models.Distance.COSINE # 余弦相似度)
特点:Qdrant会自动对Cosine集合中的向量做L2归一化,加速距离计算。一旦归一化后,Cosine、Dot Product和Euclidean对固定查询会给出相同的排序结果。所以如果你不确定选哪个,Cosine是最安全的默认值。
2.2 Dot Product(点积)—— 保留原始值
直接计算向量内积,同时考虑方向和大��。
distance=models.Distance.DOT
适用场景:需要保留向量原始值的场景,或嵌入模型明确推荐点积时使用。
2.3 Euclidean(欧几里得距离)—— 绝对距离敏感
计算两点间直线距离,对尺度敏感。
vectors_config = models.VectorParams( size=2048, distance=models.Distance.EUCLID)
适用场景:绝对距离敏感的向量类型。单个维度上的大偏差会以平方方式影响总距离。
2.4 Manhattan(曼哈顿距离)—— 抗异常值
计算各维度绝对差之和,像在城市街区中沿直线行走的距离。
distance=models.Distance.MANHATTAN
适用场景:稀疏数据、需要鲁棒处理异常值的场景。单个维度的极端偏差不像欧几里得那样被放大。
2.5 选型总结
| | |
|---|
| Cosine | | |
| Dot | | |
| Euclidean | | |
| Manhattan | | |
⚠️ 黄金原则:使用第三方嵌入模型时,优先看模型文档推荐的度量方式。如果文档没说明,就选 Cosine。
三、向量维度:跟嵌入模型走
Qdrant 的向量维度(size)必须与嵌入模型的输出维度一致,创建集合时一次性定死。
| |
|---|
| OpenAI text-embedding-3-large | |
| OpenAI text-embedding-ada-002 | |
| |
| |
| |
# 以 BGE 为例,输出维度为 1024vectors_config = models.VectorParams( size=1024, # ⬅️ 必须与嵌入模型匹配 distance=models.Distance.COSINE)
⚠️ Qdrant支持的最大向量维度为 65,535。同一个集合内的所有同名向量必须维度一致,但可以通过命名向量(Named Vectors)在同一集合中使用不同维度的向量。
四、量化开关:用精度换速度
量化是Qdrant的空间压缩技术,通过降低向量精度来减少内存占用、加速搜索。
4.1 四种量化方式对比
| | | |
|---|
| Scalar(标量) | | | |
| Binary(二进制) | | | |
| Product(乘积) | | | |
| TurboQuant | | | |
4.2 Scalar 量化配置
将每个浮点数从 32位压缩到 8位,实现 4× 压缩:
from qdrant_client import modelsclient.create_collection( collection_name="articles", vectors_config=models.VectorParams( size=768, distance=models.Distance.COSINE, ), quantization_config=models.ScalarQuantization( scalar=models.ScalarQuantizationConfig( type=models.Datatype.INT8, # int8量化 always_ram=True, # 量化后的向量常驻内存 ) ),)
4.3 Binary 量化配置
将每个分量压缩为1-2比特,适合高维向量:
quantization_config=models.BinaryQuantization( binary=models.BinaryQuantizationConfig( always_ram=True, # 量化后常驻内存加速检索 ))
4.4 重要注意事项
- • ⚠️ 启用量化后不能删除原始全精度向量——Qdrant需要全精度向量来进行重索引、重评分等操作
- • ✅ 量化统计信息(偏移量和alpha)从每个段的全精度向量中导出
- • ✅
always_ram=True 让量化后的向量常驻内存,大幅提升搜索速度
五、分片数量与副本数:扩缩容的基础
5.1 分片数量(Shard Number)
集合中的数据按逻辑分片(Shards)组织。分片是写入和搜索的最小并行单元。
client.create_collection( collection_name="articles", vectors_config=models.VectorParams( size=300, distance=models.Distance.COSINE, ), shard_number=6, # 逻辑分片数)
💡 官方推荐:从 12 个分片起步。这样未来扩容时不需要重新分片。
5.2 副本数(Replication Factor)
副本决定了每个分片的物理拷贝数量,用于高可用容灾。
# 6个分片 × 2个副本 = 集群中12个物理分片client.create_collection( collection_name="articles", vectors_config=models.VectorParams( size=300, distance=models.Distance.COSINE, ), shard_number=6, replication_factor=2, # 每个分片2个副本)
5.3 物理分片计算公式
物理分片数 = 分片数 × 副本数 × 节点数
⚠️ 副本数不能超过节点数,否则多余的副本会处于离线状态。
六、Python SDK 完整实操:CRUD + 搜索 + 过滤
6.1 环境准备
# 安装 Qdrant Python 客户端pip install qdrant-client# 安装 BGE 嵌入模型(可选)pip install FlagEmbedding sentence-transformers
6.2 连接 Qdrant
from qdrant_client import QdrantClient# 本地连接client = QdrantClient(url="http://localhost:6333")# 内存模式(测试用)client = QdrantClient(":memory:")# 持久化模式(本地磁盘)client = QdrantClient(path="path/to/db")# 远程连接(含 API Key)client = QdrantClient( url="https://your-cluster.qdrant.io", api_key="your_api_key")
6.3 创建 Collection
from qdrant_client import QdrantClient, modelsclient = QdrantClient("http://localhost:6333")# 删除同名集合(如果存在)client.delete_collection(collection_name="articles", ignore=False)client.create_collection( collection_name="articles", vectors_config=models.VectorParams( size=1024, # BGE输出维度 distance=models.Distance.COSINE, ), shard_number=1, # 单机1个分片 replication_factor=1, # 副本数)# 创建 payload 索引(加速过滤)client.create_payload_index( collection_name="articles", field_name="category", field_schema=models.PayloadSchemaType.KEYWORD,)client.create_payload_index( collection_name="articles", field_name="publish_date", field_schema=models.PayloadSchemaType.DATETIME,)
6.4 批量灌入 BGE Embedding + 文档元数据
from qdrant_client import modelsfrom FlagEmbedding import BGEM3FlagModel# 加载 BGE 模型model = BGEM3FlagModel('BAAI/bge-m3', use_fp16=True)# 准备文档列表documents = [ { "text": "Qdrant是一款高性能的向量数据库", "title": "Qdrant简介", "category": "技术", "tags": ["向量数据库", "AI"], "publish_date": "2026-08-01T00:00:00Z", }, { "text": "OpenClaw是现象级开源项目,GitHub星标突破36万", "title": "OpenClaw趋势分析", "category": "技术", "tags": ["开源", "AI工具"], "publish_date": "2026-07-15T00:00:00Z", }, { "text": "Python编程入门教程,从零开始学Python", "title": "Python入门", "category": "教程", "tags": ["Python", "编程"], "publish_date": "2026-06-20T00:00:00Z", }, { "text": "机器学习经典算法详解与实战", "title": "机器学习实战", "category": "教程", "tags": ["机器学习", "AI"], "publish_date": "2026-08-05T00:00:00Z", },]# 批量生成向量texts = [doc["text"] for doc in documents]embeddings = model.encode(texts)# 批量写入 Qdrantpoints = [ models.PointStruct( id=i, vector=embedding.tolist(), payload={ "title": doc["title"], "category": doc["category"], "tags": doc["tags"], "publish_date": doc["publish_date"], }, ) for i, (doc, embedding) in enumerate(zip(documents, embeddings))]client.upsert(collection_name="articles", points=points)print(f"✅ 成功写入 {len(points)} 个点")
6.5 基础相似度搜索:召回 TopK
# 生成查询向量query_embedding = model.encode(["向量数据库原理"])# 搜索最相似的 Top 3search_results = client.search( collection_name="articles", query_vector=query_embedding[0].tolist(), limit=3,)# 打印结果for rank, result in enumerate(search_results, 1): print(f"第{rank}名: {result.payload['title']} " f"(相似度: {result.score:.4f})") # → 第1名: Qdrant简介 (相似度: 0.8923) # → 第2名: OpenClaw趋势分析 (相似度: 0.7654)
6.6 按 ID 单点查询
# 通过 ID 检索指定点point = client.retrieve( collection_name="articles", ids=[0], # 传入点ID列表 with_payload=True, # 返回 payload with_vector=False, # 不返回向量(节省内存))print(point[0].payload)# → {'title': 'Qdrant简介', 'category': '技术', ...}
6.7 删除指定 Point
# 删除单个点client.delete( collection_name="articles", points_selector=models.PointIdsList(points=[2]),)print("✅ 已删除 ID=2 的点")
6.8 更新向量 / 元数据
# Upsert(插入或更新)——覆盖原有数据client.upsert(collection_name="articles", points=[ models.PointStruct( id=0, # 已有ID → 更新 vector=query_embedding[0].tolist(), # 新向量 payload={ "title": "Qdrant简介(修订版)", # 新标题 "category": "技术", "tags": ["向量数据库", "AI", "检索"], # 新增标签 "publish_date": "2026-08-06T00:00:00Z", }, ),])print("✅ 已更新 ID=0 的点和元数据")# 仅更新 payload(不修改向量)client.set_payload( collection_name="articles", payload={"is_featured": True}, # 追加字段 points=[1], # 指定点ID列表)
6.9 Payload 条件过滤检索
这是 Qdrant 的杀手级能力 —— 向量相似度 + 精确过滤,单次完成:
from qdrant_client import modelsquery_embedding = model.encode(["AI技术趋势"])# 按分类筛选results = client.search( collection_name="articles", query_vector=query_embedding[0].tolist(), query_filter=models.Filter( must=[ models.FieldCondition( key="category", match=models.MatchValue(value="技术"), ), ], ), limit=5,)# 多条件组合过滤:分类 + 标签results = client.search( collection_name="articles", query_vector=query_embedding[0].tolist(), query_filter=models.Filter( must=[ models.FieldCondition( key="category", match=models.MatchValue(value="技术"), ), models.FieldCondition( key="tags", match=models.MatchValue(value="AI"), ), ], ), limit=5,)# 时间范围筛选results = client.search( collection_name="articles", query_vector=query_embedding[0].tolist(), query_filter=models.Filter( must=[ models.FieldCondition( key="publish_date", range=models.Range( gte="2026-07-01T00:00:00Z", # 大于等于 lte="2026-08-06T00:00:00Z", # 小于等于 ), ), ], ), limit=10,)# 排除条件(must_not)results = client.search( collection_name="articles", query_vector=query_embedding[0].tolist(), query_filter=models.Filter( must_not=[ models.FieldCondition( key="category", match=models.MatchValue(value="教程"), ), ], ), limit=5,)# 或条件(should)results = client.search( collection_name="articles", query_vector=query_embedding[0].tolist(), query_filter=models.Filter( should=[ models.FieldCondition( key="category", match=models.MatchValue(value="技术"), ), models.FieldCondition( key="tags", match=models.MatchValue(value="机器学习"), ), ], ), limit=5,)
⚠️ 过滤操作符说明:
- •
should —— 至少一个条件满足即可(OR)
七、完整配置参考表
| | |
|---|
size | | |
distance | | |
shard_number | | |
replication_factor | | |
on_disk | | |
on_disk_payload | | |
quantization_config | | |
hnsw_config.m | | |
hnsw_config.ef_construct | | |
八、总结
今天从实操角度出发,完整走了一遍 Qdrant 基础配置项和 Python SDK 使用流程:
- 1. Docker 部署 —— 一键拉起 + Web面板可视化
- 2. 距离度量 —— Cosine最安全,依模型文档选
- 4. 量化开关 —— Scalar/二进制/TurboQuant/Product 按需选择
- 5. 分片与副本 —— 12分片起步,副本数为容灾冗余
- 6. Python SDK实操 —— CRUD全链路 + 搜索召回 + payload过滤
建议把代码保存到本地跑一遍,Qdrant的学习曲线就是这样的:跑通了就都明白了。
📢 关注"大强哥爱编程"公众号,获取更多AI技术前沿资讯!
🌟 喜欢这篇文章?请点赞、转发、收藏!有任何问题或建议,欢迎在评论区留言交流!
#大强哥爱编程 #Qdrant #向量数据库