ChromaDB Collections (集合管理)
Collection 设计这件事,很多人一开始不重视,后面最容易返工。因为一旦文档量上来,集合边界、id 规则和 metadata 结构都会直接影响检索质量和维护成本。
你可以把 Collection 理解成关系型数据库里的表,但在 RAG 项目里,它更像“检索边界”。边界划得清不清楚,决定了你后面要不要一直靠过滤条件补漏洞。
1. 集合的基本操作
创建与获取
# 创建新集合,如果已存在则报错
collection = client.create_collection(name="test_name")
# 如果不存在则创建,如果已存在则获取
collection = client.get_or_create_collection(name="test_name")
# 仅获取已存在的集合
collection = client.get_collection(name="test_name")
# 删除集合
client.delete_collection(name="test_name")
2. 数据结构详解
当你向集合 add 数据时,可以包含以下四个部分:
ids(必填): 每个项的唯一字符串标识符。embeddings(可选): 如果你自己计算了向量,传到这里。documents(可选): 原始文本。如果没传 embeddings,Chroma 会根据这些文本自动生成。metadatas(可选): 键值对字典,用于后续的精细化过滤。
读者导向建议
- 个人项目:先定一套稳定的 metadata 字段(如
source、topic、lang) - 团队项目:约定
id生成规则,避免多人写入冲突 - 生产项目:把删除策略和归档策略提前设计,不要等库变大后再补
这几条看着像管理问题,实际上都是检索问题。因为只要集合和 metadata 没定住,你的召回噪音就会越来越高。
3. 更新与删除数据
# 更新已存在的项
collection.update(
ids=["id1"],
metadatas=[{"status": "archived"}],
)
# Upsert (存在则更新,不存在则添加)
collection.upsert(
ids=["id1", "id3"],
documents=["新的内容", "新添加的内容"]
)
# 根据 ID 删除
collection.delete(ids=["id1"])
# 根据元数据过滤删除
collection.delete(where={"status": "archived"})
4. 强大的过滤查询 (Where)
Chroma 支持基于元数据和文档内容的复杂过滤。
元数据过滤 (where)
results = collection.query(
query_texts=["查询文本"],
where={"source": "notion"}, # 仅搜索来源是 notion 的数据
n_results=5
)
一句轻松提醒:
没有 metadata 的向量库,就像没有标签的衣柜。
衣服都在,但早上赶时间时你只会怀疑人生。
我一般至少会先留 source、lang、doc_type、updated_at 这类字段。先别管以后会不会全用上,留接口总比后面重建库轻松。
文档内容过滤 (where_document)
results = collection.query(
query_texts=["查询文本"],
where_document={"$contains": "重要"} # 仅搜索包含“重要”字样的文档
)
5. 计算距离 (Distance Metrics)
你可以选择不同的数学方法来计算“相似度”:
l2: 平方 L2 范数(默认)。ip: 内积。cosine: 余弦相似度。
在创建集合时指定:
collection = client.create_collection(
name="my_collection",
metadata={"hnsw:space": "cosine"}
)
别一开始就在距离度量上折腾太久。真实项目里,更常见的收益还是来自文档切块和 metadata 设计,而不是把 l2 和 cosine 来回换。
下一步:了解 Chroma 的核心——Embedding 模型自定义。