get:按条件取数据

🎉摘要:本文详细讲解ChromaDB中collection.get()方法的用法,涵盖方法签名、ids、where、limit、offset、where_document、include等参数说明,演示按ID查询、分页查询、字段返回控制及data_loader加载图片数据的实战示例,帮助开发者掌握非向量相似度的元数据/文本过滤查询。

注意,get 用于按条件直接读取集合内的原始数据记录,属于元数据 / ID / 文本过滤查询,不是向量相似度检索。

方法签名

方法签名如下:

collection.get(
    ids=None,              # 只取这几个 id
    where=None,            # 元数据过滤
    limit=None,            # 最多返回多少条
    offset=None,           # 跳过多少条
    where_document=None,   # 文档内容过滤
    include=["metadatas", "documents"],   # 要返回哪些字段
)

参数说明:

  • ids:类型为 list[str] | None,用来指定文档 ID 列表,get 仅返回列表内存在的 ID 对应的记录。例如:ids=["id001","id002"]

  • where:类型为 dict | None,用来基于 metadata 元数据的筛选过滤器,支持$eq、$ne、$gt、$gte、$lt、$lte、$in、$nin、$and、$or 操作符。例如:where={"category":"临时"}

  • limit:类型为 int | None,用来限制本次查询最多返回的记录条数。传递 None 代表不限制条数,返回所有匹配结果。

  • offset:类型为 int | None,指定查询时跳过前面 N 条数据,用于分页。从第 offset 条之后开始取数据,默认 0。

  • where_document:类型为 dict | None,基于 document 文档原文过滤,仅支持 $contains(文本包含子串)。例如:where_document={"$contains":"测试"} 查询 document 包含“测试”字符串的记录。

  • include:类型为 list[str],用来指定返回结果里携带哪些字段,可选值如下:

    • "documents":文档文本

    • "metadatas":元数据

    • "embeddings":向量(会占用大量内存,按需开启)

    • "uris":资源链接

注意了,get 方法返回的数据和传统数据库查询按行返回完全不同,它是按列返回的,格式如下:

{
  "ids": [],
  "documents": [],
  "metadatas": [],
  "embeddings": [], # 仅include包含embeddings才存在
  "uris": []        # 仅include包含uris才存在
}

上面介绍了 get 方法的语法,下面将通过示例来演示 get 的用法。

不传任何条件

当我们调用 get 时,不传递任何参数,将返回所有数据。不推荐这么去做,如果集合数据非常多,内存吃不消的。

例如:

import chromadb

client = chromadb.EphemeralClient()
collection = client.get_or_create_collection("demo_collection", embedding_function=None)

# 先灌几条数据,后面的查询 / 过滤才看得到东西
collection.add(
    ids=["r1", "r2", "r3", "r4", "r5"],
    documents=[
        "退款流程:在订单页点申请退款,3 个工作日内到账",
        "发票开具:在订单详情页申请电子发票",
        "物流查询:发货后可在物流详情里看到进度",
        "退货政策:7 天无理由退货,运费买家承担",
        "账号安全:如何修改密码和绑定手机",
    ],
    metadatas=[
        {"cat": "售后", "year": 2024, "score": 0.9, "tags": ["退款"]},
        {"cat": "财务", "year": 2023, "score": 0.5, "tags": ["发票"]},
        {"cat": "物流", "year": 2024, "score": 0.7, "tags": ["物流"]},
        {"cat": "售后", "year": 2022, "score": 0.3, "tags": ["退货"]},
        {"cat": "账号", "year": 2024, "score": 0.6, "tags": ["安全"]},
    ],
)

result = collection.get(
    ids=None,              # 只取这几个 id
    where=None,            # 元数据过滤
    limit=None,            # 最多返回多少条
    offset=None,           # 跳过多少条
    where_document=None,   # 文档内容过滤
    include=["metadatas", "documents"],   # 要返回哪些字段
)
print(f"ids={result["ids"]}")
print(f"documents={result["documents"]}")
print(f"metadatas={result["metadatas"]}")

运行示例,输出如下:

ids=['r1', 'r2', 'r3', 'r4', 'r5']
documents=['退款流程:在订单页点申请退款,3 个工作日内到账', 
'发票开具:在订单详情页申请电子发票', '物流查询:发货后可在物流详情里看到进度', 
'退货政策:7 天无理由退货,运费买家承担', '账号安全:如何修改密码和绑定手机']
metadatas=[{'year': 2024, 'cat': '售后', 'tags': ['退款'], 'score': 0.9}, 
{'cat': '财务', 'score': 0.5, 'year': 2023, 'tags': ['发票']}, 
{'cat': '物流', 'year': 2024, 'score': 0.7, 'tags': ['物流']}, 
{'tags': ['退货'], 'cat': '售后', 'score': 0.3, 'year': 2022}, 
{'year': 2024, 'cat': '账号', 'score': 0.6, 'tags': ['安全']}]

从输出可知,将整个集合数据全部输出了,如果我们要输出整个集合数据,建议显示通过 limit + offset 分页获取,不要一次性全部取出 —— 数据量大时会很慢。

还需要注意,如果你查询数据,不需要返回 embeddings,就不要让他返回,数据太大了,影响查询效率。

按 id 取

和删除的 ids 一样,用来明确获取指定 ID 的数据,非常简单,用法如下:

res = col.get(ids=["d1", "d3"])

执行代码,将返回 id 为 d1、d3 的记录信息。

分页

分页很重要,特别对于查询数据量巨大的集合。如果查询条件很简单,一次可能会返回成千上万条数据,这太影响效率了,常用做法是分页,每次一页返回 20 条、100 条,查询效率更快。

用法如下:

# 从位置0开始,查询100条记录
page1 = col.get(limit=100, offset=0)  # 如果页大小为100,这是第一页

# 从位置100开始,查询100条记录
page2 = col.get(limit=100, offset=100)  # 如果页大小为100,这是第二页

示例:

import chromadb

client = chromadb.EphemeralClient()
collection = client.get_or_create_collection("demo_collection", embedding_function=None)

# 先灌几条数据,后面的查询 / 过滤才看得到东西
collection.add(
    ids=["r1", "r2", "r3", "r4", "r5"],
    documents=[
        "退款流程:在订单页点申请退款,3 个工作日内到账",
        "发票开具:在订单详情页申请电子发票",
        "物流查询:发货后可在物流详情里看到进度",
        "退货政策:7 天无理由退货,运费买家承担",
        "账号安全:如何修改密码和绑定手机",
    ],
    metadatas=[
        {"cat": "售后", "year": 2024, "score": 0.9, "tags": ["退款"]},
        {"cat": "财务", "year": 2023, "score": 0.5, "tags": ["发票"]},
        {"cat": "物流", "year": 2024, "score": 0.7, "tags": ["物流"]},
        {"cat": "售后", "year": 2022, "score": 0.3, "tags": ["退货"]},
        {"cat": "账号", "year": 2024, "score": 0.6, "tags": ["安全"]},
    ],
)

result = collection.get(offset=1, limit=2)
print(f"ids={result["ids"]}") # ids=['r2', 'r3']

result = collection.get(offset=3, limit=2)
print(f"ids={result["ids"]}") # ids=['r4', 'r5']

注意:offset 大的时候性能会下降,因为服务端要扫过前面那些。真要导全量数据,更好的办法是按某个 metadata 字段分片(比如按 doc_id 分批取)。

include:要哪些字段

include 可选的值:

值含义
"documents"原始文本
"embeddings"向量(大,默认不带)
"metadatas"元数据
"uris"数据地址
"data"按 uri 加载回来的数据(需要集合配了 data_loader)
"distances"只在 query 里有效

get 不传 include 时默认是 ["metadatas", "documents"],不带向量。想拿向量必须显式说,就像这样:

col.get(ids=["a1"], include=["embeddings"])

传入 include 会覆盖默认值,不是追加。想全都要就写全:

col.get(ids=["a1"], include=["documents", "metadatas", "embeddings", "uris"])

include=["data"] 需要集合配了 data_loader,否则:

ValueError: You must set a data loader on the collection if loading from URIs.

例如:使用 OpenCLIPEmbeddingFunction 嵌入函数计算图片向量,ImageLoader 用于加载图片数据。

import chromadb
from chromadb.utils.data_loaders import ImageLoader
from chromadb.utils.embedding_functions import OpenCLIPEmbeddingFunction

# 创建集合时指定 data_loader
loader = ImageLoader()

# 图片嵌入函数
ef = OpenCLIPEmbeddingFunction()

client = chromadb.EphemeralClient()
collection = client.get_or_create_collection(
    name = "demo_collection",
    embedding_function = ef,
    data_loader = loader
)

# 先灌几条数据,后面的查询 / 过滤才看得到东西
collection.add(
    ids=["r1",],
    metadatas=[
        {"cat": "售后", "year": 2024, "score": 0.9, "tags": ["退款"]},
    ],
    uris = [
        "../../images/apple1.jpg"
    ]
)

result = collection.get(ids=["r1"], include=["data"])
print(result)

运行示例,输出如下:

{'ids': ['r1'], 'embeddings': None, 'documents': None, 
  'uris': ['../../images/apple1.jpg'], 'included': ['data', 'uris'], 
  'data': [array([[
       [[253, 253, 253],
        [253, 253, 253],
        [254, 254, 254],
        ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]]], shape=(118, 138, 3), dtype=uint8)], 'metadatas': [{'year': 2024, 'cat': '售后', 'tags': ['退款'], 'score': 0.9}]}
ids=['r1']

注意,为了正确运行上面代码,需要安装如下依赖:

pip install open-clip-torch pillow torch torchvision


说说我的看法
全部评论()
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号