如何让Solr在不执行全量导入时同步删除数据库已移除行对应文档?
针对你的场景,核心是利用Solr Data Import Handler(DIH)的deletedQuery机制,或者通过自定义脚本实现反向比对删除,无需执行带clean标志的全量/增量导入(后者确实会清空整个索引,完全不可取)。
方案一:利用数据库删除日志表 + DIH deletedQuery(推荐)
这是最可靠且性能友好的方式,需要数据库配合记录删除操作:
在数据库中创建删除日志表
新建一张表(比如deleted_test_view_records),用于记录每次从test_view中删除的行的x_id和删除时间:CREATE TABLE deleted_test_view_records ( x_id INT PRIMARY KEY, deleted_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP );同时,确保数据库在删除
test_view行时,自动将对应的x_id和删除时间插入该表(可以通过触发器实现)。修改DIH配置添加deletedQuery
在你的entity配置中新增deletedQuery参数,让DIH在增量导入时自动查询并删除Solr中对应的数据:<document> <entity name="myEntity" query="select * from test_view" deltaImportQuery="select * from test_view WHERE x_id= ${dih.delta.x_id}" deltaQuery="SELECT x_id from test_view where time_entered > '${dih.last_index_time}'" deletedQuery="SELECT x_id from deleted_test_view_records where deleted_time > '${dih.last_index_time}'" > <field column="x_id" name="id"/> <!-- 其他字段配置 --> </entity> </document>执行增量导入的效果
每次执行delta-import时,DIH会:- 先通过
deltaQuery获取新增/更新的x_id,用deltaImportQuery导入对应数据 - 同时通过
deletedQuery获取上次增量后被删除的x_id,自动向Solr发送删除请求,同步删除这些ID对应的文档 - 全程不会清空索引,只处理增量的增删改
- 先通过
方案二:无删除日志表时的反向比对(备选)
如果无法修改数据库创建删除日志表,可以通过定期比对数据库和Solr的ID集合来实现删除:
导出数据库当前所有有效x_id
每隔20分钟(和增量导入同步),执行SQL导出test_view中所有x_id到临时文件:COPY (SELECT x_id FROM test_view) TO '/tmp/current_ids.txt';获取Solr中所有索引的ID
通过Solr的selectAPI查询所有ID(注意分页处理,避免内存溢出):curl "http://your-solr-host:8983/solr/your-collection/select?q=*:*&fl=id&rows=10000&start=0" | jq -r '.response.docs[].id' > /tmp/solr_ids.txt找出需要删除的ID
使用命令行工具比对两个文件,找出存在于Solr但不在数据库中的ID:comm -23 <(sort /tmp/solr_ids.txt) <(sort /tmp/current_ids.txt) > /tmp/to_delete_ids.txt批量删除Solr中的无效文档
将需要删除的ID批量发送给Solr的更新API:# 生成JSON格式的删除请求 echo '{"delete": {"id": [' > /tmp/delete_request.json paste -sd "," /tmp/to_delete_ids.txt >> /tmp/delete_request.json echo ']}}' >> /tmp/delete_request.json # 发送请求到Solr curl -X POST -H "Content-Type: application/json" http://your-solr-host:8983/solr/your-collection/update -d @/tmp/delete_request.json # 提交更改 curl http://your-solr-host:8983/solr/your-collection/update -d '<commit/>'注意:此方案对性能有一定要求,若数据库规模极大,导出全量ID可能耗时,建议根据业务场景优化(比如按时间分片比对)。
关键提示
- 绝对不要使用
clean=true的增量导入,它会先清空整个Solr索引,再导入增量数据,完全不符合你的需求。 - 方案一的触发器需要确保在删除
test_view行时,无论通过什么方式删除(批量删除、单条删除),都能将x_id写入删除日志表,避免遗漏。
内容的提问来源于stack exchange,提问作者Mar

