
collection.query() 返回嵌套列表(如 ids: [['id1','id2']]),因其支持多查询并行检索;而 collection.get() 返回扁平列表(如 ids: ['id1','id2']),因其面向单次精确获取——二者语义不同,结构差异是设计使然,非 bug。
`collection.query()` 返回嵌套列表(如 `ids: [['id1','id2']]`),因其支持**多查询并行检索**;而 `collection.get()` 返回扁平列表(如 `ids: ['id1','id2']`),因其面向**单次精确获取**——二者语义不同,结构差异是设计使然,非 bug。
在 ChromaDB 中,query() 和 get() 虽同属读取操作,但定位截然不同:前者是语义驱动的近似搜索(ANN),后者是ID 或条件驱动的精确查找。这种根本性差异直接决定了其返回数据的结构设计。
✅ query():为多查询而生的嵌套结构
query() 的核心能力是支持 批量语义查询。当你传入 query_texts=["问题A", "问题B"],ChromaDB 会为每个查询文本独立执行一次向量相似性搜索,并将结果按查询顺序组织为「外层列表」,每个子列表对应一个查询的 top-k 结果:
results = collection.query(
query_texts=["机器学习是什么?", "Transformer 架构原理"],
n_results=3
)
print(results["ids"])
# 输出示例:
# [['ml_intro', 'ml_fundamentals', 'supervised_learning'],
# ['transformer_overview', 'attention_mechanism', 'llm_arch']]-
results["ids"][0]→ 第一个查询匹配的 3 个文档 ID -
results["documents"][1]→ 第二个查询匹配的 3 个原始文本 -
results["distances"][0][2]→ 第一个查询与第 3 个结果的距离值
因此,ids、documents、distances 等字段均为 List[List[Any]] 类型——这是明确的、可预测的接口契约,便于批量处理多意图用户请求(如 RAG 中并行检索多个子问题)。
✅ get():为确定性获取而设的扁平结构
get() 的职责是精准定位已知实体,例如根据 ID 列表回溯原文,或按元数据过滤筛选记录。它不涉及向量化或相似度计算,仅做索引查表:
# 精确获取指定 ID 的文档
exact_docs = collection.get(ids=["ml_intro", "transformer_overview"])
# 或按元数据条件过滤(需插入时已带 metadata)
filtered = collection.get(
where={"category": "architecture"},
include=["documents", "metadatas"]
)其返回始终是单层列表:ids: ['id1','id2']、documents: ['txt1','txt2']。因为「一次 get 调用 = 一次逻辑查询动作」,不存在歧义或分组需求。
⚠️ 注意事项与最佳实践
-
勿混淆语义与精确场景:不要用
get()替代query()做模糊匹配,也不要用query()查找已知 ID(效率低且结构冗余)。 -
解析时务必判空与解包:对
query()结果,推荐使用results["ids"][0]获取首个查询结果(即使只传一个 query_text);若需统一处理,可用itertools.chain.from_iterable(results["ids"])展平。 -
include参数控制字段可见性:两者均支持include=["documents","metadatas","distances"],但distances仅对query()有效(get()不计算距离);embeddings需显式启用且影响性能。 -
性能提示:
get()是 O(1) 索引访问,query()是 O(log n) 近似搜索——高并发下应避免在循环中高频调用query()做单 ID 查找。
总之,这种结构差异不是缺陷,而是 ChromaDB 对「搜索(search)」与「获取(fetch)」两种范式的清晰解耦。理解其背后的设计哲学,才能写出健壮、可维护的向量检索逻辑。

















