Appearance
4.3.4 新增、修改、删除数据分别怎么同步到索引?
先给结论:新增、修改、删除虽然都属于“数据变了”,但它们对索引的影响完全不同。把三类变化混成一种写入动作,通常就是旧数据残留、重复索引和脏结果的开始。
所以更稳的同步思路通常不是“统一重跑一下”,而是分别处理:
- 新增:把新对象写进去
- 修改:替换受影响对象
- 删除:让旧对象彻底失效或物理删除
一、新增数据怎么同步
新增是三类变化里最简单的一类。
一般流程是:
- 识别到新文档或新记录
- 做清洗和切块
- 生成稳定 ID 和 metadata
- 写入索引
新增最需要注意的不是“能不能写进去”,而是“写进去以后能不能和已有对象稳定共存”。
至少要保证:
doc_id不冲突chunk_id生成规则稳定- metadata 字段完整
- 不会把草稿、测试数据、未发布数据提前写进生产索引
二、修改数据怎么同步
修改是最容易被低估的一类。
因为修改通常不是简单“覆盖一下文本”,而是要回答:
- 哪些 chunk 受影响
- 旧 chunk 怎么处理
- 版本关系怎么维护
一个更稳的处理顺序通常是:
- 根据
doc_id找到该文档已有索引对象 - 对最新内容重新清洗和切块
- 生成新对象集合
- 对比新旧对象
- 对变化对象做 upsert
- 对已经不存在的旧对象做 delete 或失效
这里最关键的是:修改不是只加新对象,还要处理旧对象退出。
如果只做 upsert,不处理旧对象,系统很快就会堆积重复内容和历史残留。
三、删除数据怎么同步
删除在生产环境里经常比新增更重要。
因为删除通常意味着:
- 内容已过期
- 权限已失效
- 资料不再可见
- 文档被撤回
如果源数据已经删除,但索引对象还残留,用户就可能继续搜到不该出现的内容。
更稳的删除路径通常有两种:
1. 物理删除
也就是直接把索引对象删掉。
适合:
- 文档确认下线
- 数据不再需要保留
- 没有保留历史版本的要求
优点是结果最干净,缺点是回滚能力较弱。
2. 逻辑失效
也就是保留对象,但把它标记成:
status = inactiveis_deleted = truevalid_to < now
然后在检索前过滤掉。
适合:
- 需要审计或回查
- 可能需要回滚
- 删除动作要分阶段生效
优点是可恢复、可追踪,缺点是你必须确保过滤逻辑绝对稳定。
一个更实际的对照表
你可以先把三类变化理解成下面这样:
| 变化类型 | 主要动作 | 最容易出的问题 |
|---|---|---|
| 新增 | 新建索引对象 | ID 不稳定、未发布内容误入库 |
| 修改 | 重新生成并替换受影响对象 | 旧 chunk 残留、重复对象并存 |
| 删除 | 物理删除或逻辑失效 | 源数据没了,索引里还残留 |
这也是为什么不能把三类变化统一粗暴处理成“重新写一次”。
一个最小示意
python
def sync_change(event):
if event["op"] == "create":
chunks = build_chunks(event["doc"])
upsert_chunks(chunks)
elif event["op"] == "update":
old_chunk_ids = load_chunk_ids(event["doc_id"])
new_chunks = build_chunks(event["doc"])
new_chunk_ids = [chunk["chunk_id"] for chunk in new_chunks]
upsert_chunks(new_chunks)
delete_chunks([cid for cid in old_chunk_ids if cid not in new_chunk_ids])
elif event["op"] == "delete":
delete_chunks_by_doc_id(event["doc_id"])这段代码只是示意,但至少体现了一个关键点:
不同类型的变化,索引侧动作应该不同。
实际落地时,最值得先做好的 4 件事
如果你准备把这三类同步做稳,至少先确保:
- 每篇文档都有稳定
doc_id - 每个索引对象都有稳定
chunk_id - 每次同步都有可追踪的变更事件或时间戳
- 删除动作有明确策略,到底是物理删还是逻辑失效
这 4 件事没站稳,后面很容易出现:
- 改了一次,结果多了一份
- 删了源文档,检索里还在
- 回答偶尔命中历史版本
一个常见误区
很多人会把“修改”处理成:
- 新内容直接 upsert,旧对象先不管
这短期看似乎能用,长期几乎一定会变脏。
因为切块一旦变化,旧对象就未必会被覆盖,结果就是:
- 新块写进来了
- 旧块也还在
- 同一主题在索引里出现两到三套表述
这正是很多系统“越更新越乱”的根源。
一句话总结
新增、修改、删除三类变化必须分开处理。新增要稳定写入,修改要替换受影响对象并清掉旧对象,删除要确保旧内容真正退出检索范围。把三类变化都当成同一种写入动作,索引很快就会变脏。