在Android中使用Sqlite全文搜索对非英文字符的Unicode支持

时间:2015-04-16 08:30:58

标签: android sqlite unicode full-text-search

滚动到最后跳过解释。

背景

在我的Android应用中,我想使用非英语Unicode文本字符串来搜索存储在SQLite数据库中的文本文档/字段中的匹配项。我已经学会了(所以我认为)我需要做的是实现一个Full Text Search with fts3/fts4,这就是我过去几天一直在学习的东西。 Android支持FTS,如文档Storing and Searching for Data和博文Android Quick Tip: Using SQLite FTS Tables中所示。

问题

一切都很好看,但后来我读了2012年3月的博文The sorry state of SQLite full text search on Android,其中说

  

构建全文搜索索引的第一步是分解   将文本内容转换为单词,即标记。那些令牌就是   进入一个特殊的索引,让SQLite执行得非常快   基于令牌(或一组令牌)进行搜索。

     

SQLite有两个内置的tokenizers,它们都只考虑令牌   由US ASCII字符组成。所有其他非美国ASCII字符   被认为是空白。

之后我还发现了this StackOverflow answer @CL.(根据标签和声誉,似乎是SQLite的专家)回答有关匹配越南字母与不同变音符号的问题:

  

您必须使用可以处理Unicode的标记生成器创建FTS表   字符,即ICU或UNICODE61。

     

请注意,这些令牌化程序可能并非全部可用   Android版本,以及Android API不公开任何内容   用于添加用户定义的标记化器的函数。

This 2011 SO answer似乎确认Android不支持两个基本simpleporter之外的标记化程序。

这是2015年。这种情况有没有更新?我需要使用我的应用程序支持全文搜索,而不仅仅是拥有新手机的人(即使最新的Android版本现在支持它)。

潜在的部分解决方案?

我发现很难相信FTS根本无法使用Unicode。 simple令牌化工具的documentation表示

  

术语是符合条件的符合条件的连续序列   字符都是字母数字字符和所有字符   Unicode代码点值大于或等于128 。所有其他   将文档拆分为术语时,将丢弃字符。其   唯一的贡献是分开相邻的条款。 (强调添加)

这让我希望Android中仍然可以支持一些基本的Unicode功能,即使不支持大写和变音符号(以及具有不同Unicode代码点的各种其他等效字母形式)之类的东西。

我的主要问题

如果我只使用由空格分隔的文字Unicode字符串标记,我可以在Android中使用带有非英语Unicode文本的SQLite FTS(代码点> 128)吗? (也就是说,我正在搜索文本中出现的确切字符串。)

更新

2 个答案:

答案 0 :(得分:3)

补充答案

我最终做了@CL推荐的内容,并且能够成功实现Unicode的全文搜索。这些是我遵循的基本步骤:

  1. 用空格字符替换不属于单词部分的所有Unicode字符(> = 128)。
  2. (可选)将特定字符替换为更常规的字符。例如,ēèé都可以用e替换(如果需要这种通用搜索)。这不是必需的,但如果您不这样做,那么搜索é只会返回包含é的文档,而搜索e只会返回e的文档(而不是é)。
  3. 使用在步骤1和2中创建的修改后的文本填充虚拟FTS表。
  4. 使用未修改的文本填充普通表。当然,模式和文档数量必须与创建FTS表时相同。
  5. 使用外部内容表将虚拟FTS表与普通文本表/列链接,这样就不会存储已修改文本的副本,只存储从该文本创建的文档ID。
  6. 请阅读Full text search example in Android以获取有关如何创建FTS表并将其链接到普通表的说明。这花费了很长时间才弄明白,但最终它甚至对于大量文档进行了非常快速的全文搜索。

    如果您需要更多详细信息,请在下面发表评论。

答案 1 :(得分:2)

Unicode字符的处理类似于' normal'字母,因此您可以在FTS数据和搜索字词中使用它们。 (前缀搜索也应该有用。)

问题是Unicode字符不是规范化,即所有字符都被视为字母(即使它们实际上是标点符号( - †),或其他非字符) - 字符(☺♫)),并且不会合并大写/小写,并且不会删除变音符号。
如果要正确处理这些情况,则必须在将文档插入数据库之前以及使用搜索术语之前手动执行这些规范化。