delete 删除数据

🎉摘要:本文介绍使用 delete 从 chroma 中删除数据,delete 支持通过 id、where 条件匹配,以及通过limit限制每次删除数据的最大数量。

前面介绍了如何新增、修改数据,要从 Chroma 中删除数据,请使用 delete() 方法。

删除数据要谨慎,一旦删除,数据不能恢复。删除数据前,最好将删除的数据导出来备份,然后再进行删除。

方法签名

方法签名如下:

collection.delete(
    ids=None,
    where=None,
    where_document=None,
    limit=None,
)

参数说明:

  • ids:类型为 list[str] | None,表示要删除的文档 id 列表。例如:ids=["id1", "id2"],直接按主键删除指定条目。

  • where:类型为 dict | None,元数据过滤条件,根据 metadata 字段筛选待删除数据。 采用 Chroma 的查询过滤语法。例如:where={"type": "news"},删除 metadata 里 type 等于 news 的所有记录。 支持操作符:$eq、$gt、$gte、$lt、$lte、$ne、$in、$nin

  • where_document:类型为 dict | None,文档内容过滤,根据原始文本 document 内容筛选删除。 仅支持 $contains(文本包含子串) 例如:where_document={"$contains":"demo"} 删除document 文本中含有 demo 的记录

  • limit:类型为 int | None,表示删除数量上限,限制本次最多删除多少条,防止一次性误删大量数据。

注意:

  • 多个条件同时写:逻辑 AND,必须全部满足才会删除

  • 删除是永久删除,无法恢复!建议先使用 collection.get() 用同样条件查询,确认结果再执行 delete 操作。

  • 至少提供其中一种筛选条件:ids / where / where_document,不能全部为空(不允许一键清空全库),否则抛出如下错误,例如:

import chromadb

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

try:
    collection.delete(
        ids=None,
        where=None,
        where_document=None,
        limit=None,
    )
except Exception as e:
    print("delete 不给条件就会被拒(防手滑删库,必须显式指定删哪些):", type(e).__name__, e)

运行代码,输出如下:

delete 不给条件就会被拒(防手滑删库,必须显式指定删哪些): 
ValueError At least one of ids, where, or where_document must be provided in delete.

下面将分别介绍按 ids、where、where_document 进行删除。

按 id 删

这个最好理解,也最为简单,和关系型数据库中的根据主键删除是一样的,用法如下:

col.delete(ids=["d1", "d2"])

示例:

import chromadb

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

# 准备数据
collection.add(
    ids=["q1", "q2", "q3", "q4"],
    documents=[
        "订单付款后多久发货?一般 48 小时内出库",
        "如何申请退款?在订单详情页点击申请退款",
        "发票怎么开?在个人中心-发票管理里申请电子发票",
        "快递丢了怎么办?联系客服补发或全额退款",
    ],
    metadatas=[
        {"category": "物流"},
        {"category": "售后"},
        {"category": "财务"},
        {"category": "售后"},
    ],
)

# 删除数据
collection.delete(
    ids=["q1", "q3"], # 指定要删除记录的ID
    where=None,
    where_document=None,
    limit=None,
)

# 查看数据
result = collection.get(limit=100, offset=0, include=["documents", "metadatas"])
ids = result["ids"]
print(f"ids={result["ids"]}")
print(f"documents={result["documents"]}")
print(f"metadatas={result["metadatas"]}")

运行示例,输出如下:

ids=['q2', 'q4']
documents=['如何申请退款?在订单详情页点击申请退款', '快递丢了怎么办?联系客服补发或全额退款']
metadatas=[{'category': '售后'}, {'category': '售后'}]

从输出可知,id 为 q1 和 q2 的记录被删除了。

按元数据删

即根据记录中的 metadatas 数据,采用过滤的方式进行删除,满足条件则删除,否则不删除。这是不是类似关系型数据库中的 where 条件。

使用方式如下:

import chromadb

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

# 删除数据
# 1. $eq 等于(简写形式,直接写值等价 $eq)
collection.add(ids=["d1"], embeddings=[[0.1, 0.2, 0.3]], documents=["d1"], 
               metadatas=[{"category": "临时", "year": 2024}])
collection.delete(where={"category": "临时"})

collection.add(ids=["d2"], embeddings=[[0.1, 0.2, 0.3]], documents=["d2"], 
               metadatas=[{"category": "临时", "year": 2024}])
collection.delete(where={"category": {"$eq": "临时"}})

# 2. $ne 不等于
collection.add(ids=["d3"], embeddings=[[0.1, 0.2, 0.3]], documents=["d3"], 
               metadatas=[{"category": "正式", "year": 2024}])
collection.delete(where={"category": {"$ne": "临时"}})

# 3. $gt 大于(仅数字 int/float)
collection.add(ids=["d4"], embeddings=[[0.1, 0.2, 0.3]], documents=["d4"], 
               metadatas=[{"category": "正式", "year": 2021}])
collection.delete(where={"year": {"$gt": 2020}})

# 4. $gte 大于等于
collection.add(ids=["d5"], embeddings=[[0.1, 0.2, 0.3]], documents=["d5"], 
               metadatas=[{"category": "正式", "year": 2020}])
collection.delete(where={"year": {"$gte": 2020}})

# 5. $lt 小于
collection.add(ids=["d6"], embeddings=[[0.1, 0.2, 0.3]], documents=["d6"], 
               metadatas=[{"category": "正式", "year": 2019}])
collection.delete(where={"year": {"$lt": 2020}})

# 6. $lte 小于等于
collection.add(ids=["d7"], embeddings=[[0.1, 0.2, 0.3]], documents=["d7"], 
               metadatas=[{"category": "正式", "year": 2020}])
collection.delete(where={"year": {"$lte": 2020}})

# 7. $in 在列表内
collection.add(ids=["d8"], embeddings=[[0.1, 0.2, 0.3]], documents=["d8"], 
               metadatas=[{"category": "测试", "year": 2024}])
collection.delete(where={"category": {"$in": ["临时", "测试", "草稿"]}})

# 8. $nin 不在列表内
collection.add(ids=["d9"], embeddings=[[0.1, 0.2, 0.3]], documents=["d9"], 
               metadatas=[{"category": "草稿", "year": 2024}])
collection.delete(where={"category": {"$nin": ["正式", "发布"]}})

# 9. 多条件 AND 同时满足:chroma 1.5 不再支持多 key 隐式 AND,必须用显式 $and 包裹
collection.add(ids=["d10"], embeddings=[[0.1, 0.2, 0.3]], documents=["d10"], 
               metadatas=[{"category": "临时", "year": 2024}])
collection.delete(where={
    "$and": [
        {"category": "临时"},
        {"year": {"$lt": 2025}}
    ]
})

# 10. 显式 $and 嵌套多条件
collection.add(ids=["d11"], embeddings=[[0.1, 0.2, 0.3]], documents=["d11"], 
               metadatas=[{"category": "临时", "year": 2023}])
collection.delete(where={
    "$and": [
        {"category": "临时"},
        {"year": {"$gte": 2020}}
    ]
})

# 11. $or 或条件,满足任意一条即可
collection.add(ids=["d12"], embeddings=[[0.1, 0.2, 0.3]], documents=["d12"], 
               metadatas=[{"category": "发布", "year": 2017}])
collection.delete(where={
    "$or": [
        {"category": "临时"},
        {"year": {"$lt": 2018}}
    ]
})

# 查询记录数
print(f"集合总记录数 {collection.count()}")
# 结果:
# 集合总记录数 0

按文档内容删

该种删除方式是模糊匹配删除,如果文档中包含指定的文本,则删除。否则,不进行删除。用法如下:

import chromadb

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

# 准备数据
collection.add(
    ids=["q1", "q2", "q3", "q4"],
    documents=[
        "订单付款后多久发货?一般 48 小时内出库",
        "如何申请退款?在订单详情页点击申请退款",
        "发票怎么开?在个人中心-发票管理里申请电子发票",
        "快递丢了怎么办?联系客服补发或全额退款",
    ],
    metadatas=[
        {"category": "物流"},
        {"category": "售后"},
        {"category": "财务"},
        {"category": "售后"},
    ],
)

# 删除数据
collection.delete(
    ids=None,
    where=None,
    where_document={
        "$contains": "订单" # 删除内容包含【订单】的记录
    },
    limit=None,
)

# 查看数据
result = collection.get(limit=100, offset=0, include=["documents", "metadatas"])
ids = result["ids"]
print(f"ids={result["ids"]}")
print(f"documents={result["documents"]}")
print(f"metadatas={result["metadatas"]}")

执行完成后,id 为 q1 和 q2 的记录成功被删除:

ids=['q3', 'q4']
documents=['发票怎么开?在个人中心-发票管理里申请电子发票', '快递丢了怎么办?联系客服补发或全额退款']
metadatas=[{'category': '财务'}, {'category': '售后'}]

limit:只删 N 条

这个参数挺有用,能避免一次误删太多,一是避免在条件写错时错误删除大量数据,二是避免一次删除大量数据,导致程序长时间等待删除动作完成。

示例:

import chromadb

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

# 准备数据
collection.add(
    ids=["q1", "q2", "q3", "q4"],
    documents=[
        "订单付款后多久发货?一般 48 小时内出库",
        "如何申请退款?在订单详情页点击申请退款",
        "发票怎么开?在个人中心-发票管理里申请电子发票",
        "快递丢了怎么办?联系客服补发或全额退款",
    ],
    metadatas=[
        {"category": "物流"},
        {"category": "售后"},
        {"category": "财务"},
        {"category": "售后"},
    ],
)

# 删除数据
collection.delete(
    ids=None,
    where=None,
    where_document={
        "$contains": "订单" # 删除内容包含【订单】的记录
    },
    limit=1, # 删除限制,仅删除一条匹配记录
)

# 查看数据
result = collection.get(limit=100, offset=0, include=["documents", "metadatas"])
ids = result["ids"]
print(f"ids={result["ids"]}")
print(f"documents={result["documents"]}")
print(f"metadatas={result["metadatas"]}")

上面示例插入 4 条数据,包含【订单】字符串的记录有两条,分别是 q1 和 q2,但是仅删除了 q1,被限制一次仅能删除一条数据。最终输出如下:

ids=['q2', 'q3', 'q4']
documents=['如何申请退款?在订单详情页点击申请退款', '发票怎么开?在个人中心-发票管理里申请电子发票', '快递丢了怎么办?联系客服补发或全额退款']
metadatas=[{'category': '售后'}, {'category': '财务'}, {'category': '售后'}]


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