MongoDB 向量检索配置:Atlas Vector Search 索引创建与查询验证
MongoDB 的向量检索不是社区版单机自带的能力,而是 MongoDB Atlas 提供的 Atlas Vector Search 功能。
想在 MongoDB 里存向量并做相似度查询,需要把数据放在 Atlas 集群,为集合创建向量索引,再用 $vectorSearch 聚合阶段查询。
如果服务器上装的是社区版 mongod,按本文命令执行会找不到索引和查询阶段,应先确认环境。
先确认环境和前提
Atlas Vector Search 的硬性条件有三项:
集群运行在 MongoDB Atlas 上、
集合里有一个存数值数组的字段、
该字段的向量维度与 embedding 模型一致。
- 集群:Atlas 免费层或付费层均可创建向量索引,但免费层有资源限制,生产环境建议按数据量选择。
- 字段:向量字段必须是
double或float数组,例如embedding,长度固定,不能混入其他类型。 - 维度:常见 embedding 模型输出 384、768、1536 维,索引配置里的
numDimensions必须与写入数据完全一致,否则查询会报维度不匹配。 - 驱动:Python 环境安装
pymongo和sentence-transformers即可完成写入和查询示例。
连接字符串在 Atlas 控制台点击 Connect 获取,格式形如 mongodb+srv://。
retryWrites=true&w=majority
创建向量索引
Atlas 的向量索引通过 JSON 定义,在控制台进入集群的 Atlas Search 标签页,点击 Create Search Index,选择 JSON Editor,数据库和集合按实际填写。
索引配置示例:
{
"fields": [
{
"type": "vector",
"path": "embedding",
"numDimensions": 384,
"similarity": "cosine"
},
{
"type": "filter",
"path": "category"
}
]
}
path 指向存向量的字段,numDimensions 与模型维度一致,similarity 可选 cosine、dotProduct、euclidean。filter 类型字段用于在查询时加过滤条件,不是必须,但业务里按分类、状态过滤时很实用。
索引创建后状态会从 BUILDING 变为 READY,只有 READY 后才能查询。
写入带向量的文档
下面示例用 sentence-transformers 生成 384 维向量,写入 demo.articles 集合。
执行前确保索引已 READY,否则数据写入后不会立即被索引。
from pymongo import MongoClient
from sentence_transformers import SentenceTransformer
client = MongoClient("mongodb+srv://:@.mongodb.net/?retryWrites=true&w=majority")
col = client["demo"]["articles"]
model = SentenceTransformer("all-MiniLM-L6-v2")
docs = [
{"title": "MongoDB 索引基础", "category": "database", "text": "讲解 MongoDB 索引类型与创建方式"},
{"title": "向量检索入门", "category": "ai", "text": "介绍向量相似度检索的基本概念"},
]
for d in docs:
d["embedding"] = model.encode(d["text"]).tolist()
col.insert_many(docs)
print(col.count_documents({}))
运行后应输出插入条数。
如果报 document too large,检查向量字段是否误存了字符串或嵌套结构;
如果查询阶段报维度错误,核对 numDimensions 和模型输出维度。
用 $vectorSearch 查询并验证
$vectorSearch 必须作为聚合管道的第一个阶段,index 填索引名,queryVector 是查询文本的向量,limit 控制返回条数,numCandidates 是候选集大小,
通常设为 limit 的 10 到 20 倍以平衡召回和速度。
query_vec = model.encode("向量相似度怎么算").tolist()
pipeline = [
{
"$vectorSearch": {
"index": "vector_index",
"path": "embedding",
"queryVector": query_vec,
"numCandidates": 50,
"limit": 3,
"filter": {"category": "ai"}
}
},
{
"$project": {
"_id": 0,
"title": 1,
"text": 1,
"score": {"$meta": "vectorSearchScore"}
}
}
]
for r in col.aggregate(pipeline):
print(r)
验证要点:返回结果应包含 score 字段且按分数降序;filter 条件生效时结果只含对应分类;
把 limit 改为 1 后条数应同步变化。
如果返回空数组,先检查索引状态是否 READY、集合名和索引名是否写错、path 是否与文档字段一致。
容易踩的几个坑
- 在社区版上找 Vector Search:单机 mongod 没有
$vectorSearch阶段,控制台也没有 Atlas Search 入口,这是功能边界而不是配置错误。 - 索引未就绪就查询:新建索引需要构建时间,数据量大时更久,查询前确认状态为
READY。 - 维度不一致:更换 embedding 模型后必须重建索引并重写全部向量,不能只改查询向量。
- 过滤字段未声明:查询里用了
filter,但索引 JSON 没有对应filter字段,会报过滤字段未索引。 - 把向量当普通数组查:普通
find和$near不适用于向量字段,相似度查询只走$vectorSearch。
如果业务必须自建、不能使用 Atlas,应评估其他支持向量的数据库或搜索引擎,而不是在社区版 MongoDB 上硬套本文配置。
常见疑问
免费层能创建向量索引吗? 可以创建,但免费层集群有存储和连接数限制,适合测试和小数据量验证,生产前应评估容量。
索引名和集合名必须固定吗? 不固定,但 $vectorSearch 的 index 字段必须与创建时填写的索引名一致,改名后查询也要同步修改。
向量维度可以后期修改吗? 索引的 numDimensions 创建后不能直接改,需要删除重建索引,并按新维度重写文档向量。