为什么Telegram不能搜寻中文讯息

Telegram对于中文的支持并不很好,尤其是搜寻功能遇上汉字即与残废无异。。,原因究竟是什么呢??让我们来逐步抽丝剥茧吧

首先,我们看看Telegram核心td-lib是如何存储消息的。这是MessagesDb.cpp,从12到14行我们可以知道Telegram使用SQLite作为资料库:

#include“ td / db / SqliteConnectionSafe.h” 
#include“ td / db / SqliteDb.h” 
#include“ td / db / SqliteStatement.h”

接下来,我们可以发现这个数据库中有很多表,但是我们只关心messages_fts 这个虚拟表。那么,这个fts又是什么呢??

如果不存在,则创建虚拟表使用fts5的messages_fts(文本,content ='messages',content_rowid ='search_id',tokenize =“ unicode61 remove_diacritics 0 tokenchars'\ a'”)

原来,fts实际上全文搜索,也就是所谓的全文搜索,而fts5则是SQLite内建可以提供全文搜索的模组。

说到这里,来先打个岔谈谈字串搜寻。在高中演算法竞赛中,除了朴素的暴力解外,最常见而广为人知的方法有两种:KMP演算法与其他基于散列的演算法。前者是由资讯界史诗级教授Donald E. Knuth及Pratt,莫里斯于1977年提出。

而SQLite fts5比较类似基于hash的演算法,他的做法大约如下:

  1. 将字串以tokenizer切割成一段段的短语
  2. phrase进行hash后存进表
  3. 搜寻时也将搜寻字串以tokenizer切割成一段段的短语,在哈希表中进行搜寻

举例而言,讯息qwert qaz qsc在搜寻时只会分别匹配到qwert, ,这qaz三个qsc字串,你搜寻单独的qaer都不会匹配到。

1_xfBBZwLlwiR9cSC7GQIHA

讯息内容

1ipWHug7_9QOKLLiQ11mgDg

搜寻一个阶段,成功

1aQkSCbhs6cBySchIB0aSSg

搜寻单独q,反而失败

那问题接着来了:标记生成器根据什么切割??用以切割阶段的字元,我们称之分离器分隔符,而剩下构成的字元称之令牌。进一步来说,依据的unicode的类别,属于大号*(字母)N *(数字)Co(其他)预设为令牌,其余都被视为分隔符

因此,我们终于找到Telegram不能搜寻中文讯息的根本原因了。原来,由于unicode CJK(中日韩表意文字)绝大部分都属于Lo类别,从而,汉字语汉字间没有任何分隔符,会被整串拿去哈希,从而导致搜寻无效。

12TewrBWBsNUEiR803wLgoA

1Y1-lNA5KuQc1xiq1CHIoAA

搜寻整串CJK即成功,证实我们的推论

结语

不小心就打了一堆堆废话呢,相信大家都知道Telegram不能搜寻中文讯息的原因了。解决的方法我有想到两种,其一是手动在汉字间插入不可见的分隔符,另一种是写个客制化的tokenizer

于此将我的一点浅见拿来分享作为抛砖引玉,希望各位电神不吝指教。未来若有空我也十分希望能为Telegram社群贡献。

原文地址:https://medium.com/@nevik.w39/%E7%82%BA%E4%BB%80%E9%BA%BC-telegram-%E4%B8%8D%E8%83%BD%E6%90%9C%E5%B0%8B%E4%B8%AD%E6%96%87%E8%A8%8A%E6%81%AF-6b7d07690e6f

2 条回复 A 作者 M 管理员
  1. 试试

  2. 有下载nicegram的方法吗 兄弟

欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论