最近工作中要求实现相似文本查询的功能,我于是决定用SimHash实现。
常规思路通常分为以下四步:
1、实现SimHash算法。
2、保存文章时,同时保存SimHash为倒排索引。
3、入库时或使用定时任务,在倒排索引中找到碰撞的SimHash,保存为结果表。
4、需要查询一篇文章的相似文章时,根据文章ID,查询结果表,找到相似文章。
不过这里有个小问题,如果一篇多次入库的文章的SimHash发生变化,或者文章被删除啥的,结果表可能很难及时更新。
同时ES刚好很擅长查询与维护倒排索引,所以我想能不能直接交给ES帮我维护SimHash的倒排索引,从而跳过使用结果表呢?
那么以上逻辑会简化到3步:
1、实现SimHash算法。
2、保存文章时,同时在ES中保存SimHash字段(和正文其它字段一起)。
3、需要查询一篇文章的相似文章时,根据文章ID查到SimHash值,再去ES查询匹配的其它文章ID,不过这里需要在服务层做个汉明距离的过滤。
说干就干,以下是我的实现代码,基于网上已有的算法进行了一些修改,总之给大家抛砖引玉了,如果有做的不好的地方还请大家指出。