“去重合并”经常被想象成一个很简单的按钮:选一条保留,剩下删掉。但 enterprise/data_cleaning/models/data_merge_group.py 和 data_merge_record.py 说明,真正的企业级合并需要回答四个难题:谁是主记录、哪些字段真的不同、所有外键怎么回写、合并后怎么留痕。
一、先算相似度,不是为了好看,而是为了告诉你差异在哪里
_compute_similarity() 会拿候选记录的相似字段做交集,算出 divergent_fields 和 similarity。这一步不是可视化装饰,而是在提醒操作者:这些记录虽然被判成一组,但并不代表它们完全一致。
这很关键,因为企业真实数据去重里,重复记录往往只有 70%~90% 相似。没有差异字段提示,用户很容易在错误前提下直接合并。
二、主记录选举不是拍脑袋,可以走模型自定义,也有默认规则
_elect_master_record() 会先看业务模型自己有没有 _elect_method();没有再走 group 的默认选举逻辑。这说明官方承认“谁该留下”并不是一个对所有模型都通用的规则。
比如联系人、线索、产品、员工,保留主记录的优先级都可能不同。企业项目里最危险的做法,就是用同一套“最后创建的保留”规则处理所有模型。
三、真正麻烦的是外键与附属对象回写
_update_foreign_keys() 会搜索所有引用目标表的关系字段,然后批量把 source 指向 destination;_merge_additional_models() 还会专门处理 ir_attachment、mail_activity、ir_model_data、mail_message 等附属表;_merge_mail_followers() 则额外防止 follower 合并时触发唯一键冲突。
这才是企业去重与“手工删重复行”的本质差异:你合并的不是显示出来的两条记录,而是它们背后一整张引用网络。
四、合并之后还要决定原记录是删还是归档,并写日志
_post_merge() 会根据 removal_mode 和模型是否支持 active 字段,决定 unlink() 还是写 inactive。_log_merge() 则把被合并记录的快照和上下文发到 master record 的 chatter。
这两步共同回答了两个运维问题:
- 原记录还能不能被追溯;
- 后面谁来证明这次合并到底发生过什么。
没有日志的去重,在审计和排障场景里几乎等于没做。
实战注意事项
- 先看差异字段再点 merge:不要把“判成一组”误解成“完全相同”。
- 为关键模型定义 elect 规则:主记录选举不应只靠默认实现。
- 先理解引用网络:附件、活动、消息、followers 都可能跟着移动。
- 决定删除还是归档:审计要求高的模型通常更适合归档而不是硬删。
新手误区
- 误以为去重就是删掉一条显示重复的数据。
- 误以为 master 选谁都差不多。
- 误以为外键回写只影响少数关系字段。
- 误以为合并完成后不需要留痕。
主要源码参考
enterprise/data_cleaning/models/data_merge_group.pyenterprise/data_cleaning/models/data_merge_record.py
DISCUSSION
评论区