Chroma查询集合:从基础检索到高级过滤的完整指南
当你成功地将数据存入Chroma集合后,下一步自然是如何高效、精准地查询这些数据。Chroma提供了两套核心的查询API:相似性搜索(Query) 和 直接获取(Get) 。结合强大的元数据过滤 和全文搜索功能,你可以构建从简单到复杂的各种检索逻辑。本文将基于官方文档,为你全面解析Chroma的查询艺术。
1. 核心查询:相似性搜索(Query)
query 方法是Chroma的核心功能,它执行近似最近邻(ANN)搜索,找到与你的输入最相似的向量。
1.1 基础相似性搜索
最常用的方式是传入文本,Chroma会自动使用集合的嵌入函数将其转换为向量进行搜索。
python
python
import chromadb
# 假设你已经有了一个client和collection
# client = chromadb.Client()
# collection = client.get_collection("my_docs")
results = collection.query(
query_texts=["机器学习的应用", "深度学习的原理"], # 可以传入多个查询
n_results=5 # 返回每个查询最相似的5个结果
)
参数说明:
-
query_texts:一个文本列表,Chroma会自动嵌入它们。 -
query_embeddings:如果你已经有向量,可以直接传入。当集合没有嵌入函数时,这是必需的。向量的维度必须与集合中的一致。 -
n_results:每个查询返回的结果数量,默认为10。 -
ids:可选,如果提供,搜索将仅限定在这些ID的记录范围内。
1.2 控制返回内容
默认情况下,query 返回 documents、metadatas 和 distances。你可以使用 include 参数精确控制返回的数据。
python
python
results = collection.query(
query_texts=["人工智能"],
include=["documents", "metadatas", "embeddings", "distances"] # 返回所有字段
)
1.3 查询结果的结构
query 返回的结果是**按列组织(column-major)**的,并且每组查询的结果是分开的。一个典型的返回结构如下:
json
python
{
"ids": [["doc_1", "doc_7"]], // 外层列表对应每个查询,内层列表是结果ID
"embeddings": [[[1, 2, 3, 4], [1, 2, 3, 4]]], // 对应每个结果的向量
"documents": [["Chroma stores vectors.", "Embeddings power semantic search."]],
"metadatas": [[
{"source": "docs", "topic": "intro"},
{"source": "blog", "topic": "search"}
]],
"distances": [[0.12, 0.21]], // 距离值,越小越相似
"included": ["embeddings", "documents", "metadatas", "distances"]
}
遍历结果的小技巧:
python
python
results = collection.query(query_texts=["第一个查询", "第二个查询"])
# 外层循环:遍历每个查询的结果集
for ids_list, docs_list, metas_list in zip(results["ids"], results["documents"], results["metadatas"]):
# 内层循环:遍历一个查询返回的多个结果
for id, doc, meta in zip(ids_list, docs_list, metas_list):
print(f"ID: {id}, Doc: {doc}, Meta: {meta}")
2. 精确获取:Get 方法
当你不需要相似性排序 ,只想根据条件精确获取记录时,应该使用 get 方法。
python
python
# 根据ID获取
records_by_id = collection.get(ids=["doc1", "doc3"])
# 分页获取所有记录
all_records = collection.get(limit=50, offset=0)
# 只返回文档和元数据
records = collection.get(include=["documents", "metadatas"])
get 返回的数据结构是扁平化的,每个数组中的元素一一对应同一条记录。
json
python
{
"ids": ["doc_1", "doc_7"],
"embeddings": [[1, 2, 3, 4], [1, 2, 3, 4]],
"documents": ["Chroma stores vectors.", "Embeddings power semantic search."],
"metadatas": [{"source": "docs"}, {"source": "blog"}],
"included": ["documents", "metadatas"]
}
3. 精准过滤:元数据过滤(where)
元数据过滤是让检索结果更精准的关键。通过在 query 或 get 中使用 where 参数,你可以根据与每条记录关联的元数据进行筛选。
3.1 基础比较操作符
Chroma支持多种比较操作符:$eq(等于,可省略)、$ne(不等于)、$gt(大于)、$gte(大于等于)、$lt(小于)、$lte(小于等于)。
python
python
# 筛选 page 等于 10 的记录(两种写法等价)
collection.get(where={"page": 10})
collection.get(where={"page": {"$eq": 10}})
# 筛选 page 大于 5 且小于等于 20 的记录
collection.get(where={"page": {"$gt": 5, "$lte": 20}})
3.2 包含操作符:in 和 nin
检查元数据字段的值是否在一个列表中。
python
python
# 获取作者是 Rowling, Fitzgerald 或 Herbert 的记录
collection.get(
where={"author": {"$in": ["Rowling", "Fitzgerald", "Herbert"]}}
)
# 获取作者不是上述三人的记录(或没有author字段的记录)
collection.get(
where={"author": {"$nin": ["Rowling", "Fitzgerald", "Herbert"]}}
)
3.3 数组元数据的过滤:contains 和 not_contains
如果你在元数据中存储了数组(例如标签列表),可以使用这两个操作符进行过滤。
python
python
# 假设我们添加了带有数组元数据的记录
collection.add(
ids=["movie1", "movie2", "movie3"],
documents=["...", "...", "..."],
metadatas=[
{"genres": ["action", "comedy"], "year": 2020},
{"genres": ["drama"], "year": 2021},
{"genres": ["action", "thriller"], "year": 2022},
],
)
# 查询所有包含 "action" 标签的记录
action_movies = collection.get(
where={"genres": {"$contains": "action"}}
)
# 查询所有不包含 "comedy" 标签的记录
non_comedy = collection.get(
where={"genres": {"$not_contains": "comedy"}}
)
# 结合其他条件:2021年后上映的动作片
filtered = collection.get(
where={
"$and": [
{"genres": {"$contains": "action"}},
{"year": {"$gte": 2021}}
]
}
)
数组过滤的约束:
-
数组元素类型必须一致(如全是字符串)。
-
$contains的值必须是标量,且类型与数组元素一致。 -
空数组和嵌套数组是不允许的。
3.4 逻辑组合:and 和 or
你可以使用逻辑操作符将多个条件组合起来,构建复杂的过滤逻辑。
-
$and:满足所有条件。python
python# 筛选 page 在 5 到 10 之间的记录 collection.get(where={ "$and": [ {"page": {"$gte": 5}}, {"page": {"$lte": 10}} ] }) -
$or:满足任一条件。python
python# 筛选颜色为红色或蓝色的记录 collection.get(where={ "$or": [ {"color": "red"}, {"color": "blue"} ] })
4. 内容检索:全文搜索(where_document)
有时你需要根据文档的文本内容 进行过滤,而不是语义向量。这时可以使用 where_document 参数。它支持两种操作符:$contains/$not_contains 和 $regex/$not_regex。
4.1 关键词包含搜索
$contains 用于检查文档是否包含特定的关键词。注意:这是大小写敏感的。
python
python
# 获取所有文档中包含 "Chroma" 关键词的记录
results = collection.get(
where_document={"$contains": "Chroma"}
)
# 在相似性搜索中同时应用全文过滤
query_results = collection.query(
query_texts=["向量数据库"],
where_document={"$contains": "Chroma"}
)
4.2 正则表达式搜索
当需要更复杂的模式匹配时,可以使用 $regex。
python
python
# 查找文档中看起来像电子邮件地址的记录
email_pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
results = collection.get(
where_document={"$regex": email_pattern}
)
4.3 逻辑组合在全文搜索中的应用
where_document 同样支持 $and 和 $or 来组合多个搜索条件。
python
python
# 文档中必须同时包含 "machine" 和 "learning"
results = collection.get(
where_document={
"$and": [
{"$contains": "machine"},
{"$contains": "learning"}
]
}
)
# 文档中包含 "hello" 或 "world"
results = collection.get(
where_document={
"$or": [
{"$contains": "hello"},
{"$contains": "world"}
]
}
)
5. 组合查询:元数据过滤 + 全文搜索
Chroma 最强大的地方在于,你可以将 where(元数据过滤)和 where_document(全文搜索)结合使用,与 query 或 get 一起,实现高度精准的检索。
python
python
# 场景:查找 2021 年之后发布,文档内容包含 "Chroma",且与 "机器学习" 语义最相似的文档
advanced_results = collection.query(
query_texts=["机器学习"],
n_results=10,
where={"year": {"$gte": 2021}}, # 元数据条件
where_document={"$contains": "Chroma"} # 全文搜索条件
)
# 同样适用于 get 操作
specific_records = collection.get(
where={"author": "John"},
where_document={"$regex": ".*重要结论.*"},
limit=5
)
总结
通过本文,你已经掌握了Chroma查询集合的完整工具箱:
-
基础查询 :用
query进行语义搜索,用get进行精确获取。 -
元数据过滤 :利用
where和各种操作符($eq,$gt,$in,$contains等)对记录的标签、属性进行筛选,并可通过$and/$or构建复杂逻辑。 -
全文搜索 :利用
where_document对文档内容进行关键词包含或正则表达式匹配。 -
组合使用:将上述功能结合,实现既考虑语义相似度,又满足特定元数据和内容条件的"上帝视角"式检索。
熟练运用这些查询技巧,你将能充分挖掘Chroma集合中数据的价值,为上层应用提供精准、高效的信息支持。开始在你的RAG系统或语义搜索应用中实践吧!