Chroma 的 Collection 中,id 是字符串,同一个 Collection 下,id 全局唯一。
不同 Collection、不同 Database、不同 Tenant 之间,id 互不冲突。
注意:id 只能是字符串类型,哪怕存数字语义,也必须写成字符串 "1",不能传整数 1,否则直接报错。例如:
import chromadb
# 获取内存模式客户端
client = chromadb.EphemeralClient()
# 获取集合,如果集合不存在,则创建集合
col = client.get_or_create_collection("demo_col", embedding_function=None)
# 写入数据
col.add(ids=["m1"], embeddings=[[1, 0, 0]])
print("字符串 id 添加成功")
col.add(ids=[2], embeddings=[[1, 1, 0]])
print("数字 id 添加成功")运行示例,输出如下:
字符串 id 添加成功
Traceback (most recent call last):
...
ValueError: Expected ID to be a str, got 2 in add.除此以外,还有几个要注意的,如下:
(1)重复的 id 调用 add 不会报错,会被静默忽略(不是覆盖)。例如:
import chromadb
# 获取内存模式客户端
client = chromadb.EphemeralClient()
# 获取集合,如果集合不存在,则创建集合
col = client.get_or_create_collection("demo_col", embedding_function=None)
# 写入数据,两条数据id相同
col.add(ids=["m1"], embeddings=[[1, 0, 0]])
col.add(ids=["m1"], embeddings=[[0, 1, 0]]) # 这句无效,不报错
print(f"集合中,向量数量:{col.count()}") # 还是 1,embedding 还是 [1,0,0]
try:
# get 默认不返回向量,只返回元信息,可通过 include 配置返回那些信息
datas = col.get(ids=["m1"], include=["embeddings", "documents", "metadatas"])
print(f"查询结果:{datas}")
except Exception as e:
print("看看集合列表时出错:", type(e).__name__, e)运行上面代码,输出如下:
集合中,向量数量:1
查询结果:{'ids': ['m1'], 'embeddings': array([[1., 0., 0.]]), 'documents': [None],
'uris': None, 'included': ['embeddings', 'documents', 'metadatas'],
'data': None, 'metadatas': [None]}从输出得知,id 为 m1 的记录,embeddings 还是 [1., 0., 0.],并没有被 [0, 1, 0] 覆盖。
(2)要覆盖请用 upsert 或 update,这是新手最常见的困惑之一。例如:
import chromadb
# 获取内存模式客户端
client = chromadb.EphemeralClient()
# 获取集合,如果集合不存在,则创建集合
col = client.get_or_create_collection("demo_col", embedding_function=None)
# 写入数据,两条数据id相同
col.add(ids=["m1"], embeddings=[[1, 0, 0]])
datas = col.get(ids=["m1"], include=["embeddings", "documents", "metadatas"])
print(f"add -> 查询结果:ids={datas["ids"]}, embeddings={datas["embeddings"]}")
# 使用 update 更新数据
col.update(ids=["m1"], embeddings=[[0, 1, 0]])
datas = col.get(ids=["m1"], include=["embeddings", "documents", "metadatas"])
print(f"update -> 查询结果:ids={datas["ids"]}, embeddings={datas["embeddings"]}")
# 使用 upsert 更新数据
col.upsert(ids=["m1"], embeddings=[[0, 0, 1]])
datas = col.get(ids=["m1"], include=["embeddings", "documents", "metadatas"])
print(f"upsert -> 查询结果:ids={datas["ids"]}, embeddings={datas["embeddings"]}")运行上面代码,输出如下:
add -> 查询结果:ids=['m1'], embeddings=[[1. 0. 0.]]
update -> 查询结果:ids=['m1'], embeddings=[[0. 1. 0.]]
upsert -> 查询结果:ids=['m1'], embeddings=[[0. 0. 1.]]一些建议:
(1)建议用有业务含义的 id,比如 f"{doc_id}_chunk_{idx}"。这样去重、更新、删除都方便,也方便跟主库对齐。
(2)id 不参与检索,但它可以在 query 里当过滤条件(ids=["id1","id2"] 表示只在这几条里搜)。