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

2024-05-02

滚动到末尾以跳过说明。

背景

在我的 Android 应用程序中,我想使用非英语 Unicode 文本字符串来搜索存储在 SQLite 数据库中的文本文档/字段中的匹配项。我了解到(所以我认为)我需要做的是实施一个使用 fts3/fts4 进行全文搜索 http://www.sqlite.org/fts3.html#section_1,这就是我这几天一直在努力学习的内容。 Android 支持 FTS,如文档所示存储和搜索数据 http://developer.android.com/training/search/search.html并在博客文章中Android 快速提示:使用 SQLite FTS 表 http://blog.andresteingress.com/2011/09/30/android-quick-tip-using-sqlite-fts-tables/.

Problem

一切看起来都不错,但后来我读了 2012 年 3 月的博客文章Android 上 SQLite 全文搜索的遗憾现状 http://kmansoft.com/2012/03/17/the-sorry-state-of-sqlite-full-text-search-on-android/,其中说

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

SQLite 有两个内置的分词器 http://www.sqlite.org/fts3.html#tokenizer,并且他们都只考虑 token 由 US ASCII 字符组成。所有其他非 US ASCII 字符 被视为空白。

之后我还发现这个 StackOverflow 答案 https://stackoverflow.com/a/17399384/3681880 by @CL. https://stackoverflow.com/users/11654/cl(根据标签和声誉,他似乎是 SQLite 专家)回答有关将越南语字母与不同变音符号匹配的问题:

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

请注意,这些标记器可能不适用于所有 Android 版本,并且 Android API 不公开任何 用于添加用户定义的标记器的函数。

这个2011年的答案 https://stackoverflow.com/a/8183890/3681880似乎证实 Android 不支持超出两个基本的标记器simple and porter ones.

现在是2015年了,这种情况有什么更新吗?我需要为使用我的应用程序的每个人提供全文搜索支持,而不仅仅是拥有新手机的人(即使最新的 Android 版本现在确实支持它)。

潜在的部分解决方案?

我很难相信 FTS 根本不能与 Unicode 一起使用。这文档 http://www.sqlite.org/fts3.html#tokenizer为了simple分词器说

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

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

我的主要问题

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

Updates

  • The unicode61 分词器 https://www.sqlite.org/fts3.html#unicode61在 SQLite 版本 3.7.13 中可用。该分词器支持“完整的 unicode 大小写折叠”和“识别 unicode 空格和标点字符”。Android Lollipop(API 20+)使用 SQLite 3.8 https://stackoverflow.com/questions/2421189/version-of-sqlite-used-in-android/4377116#4377116.

补充答案

我最终按照 @CL 的建议进行了操作,并成功地使用 Unicode 实现了全文搜索。这些是我遵循的基本步骤:

  1. 将不属于单词一部分的所有 Unicode 字符 (>= 128) 替换为空格字符。
  2. (可选)用更通用的字符替换特定字符。例如,ē, è, and é都可以替换为e(如果需要这种广义搜索)。这不是必需的,但如果您不这样做,则搜索é只会返回带有以下内容的文档é,并寻找e只会返回带有以下内容的文档e(并不是é).
  3. 使用步骤 1 和 2 中创建的修改文本填充虚拟 FTS 表。
  4. 使用未修改的文本填充普通表。当然,架构和文档数量必须与创建 FTS 表时相同。
  5. 使用外部内容表将虚拟 FTS 表与普通文本表/列链接起来,这样您就不会存储修改后的文本的副本,而只会存储从该文本创建的文档 ID。

请阅读Android 中的全文搜索示例 https://stackoverflow.com/a/29926430/3681880有关如何创建 FTS 表并将其链接到普通表的说明。这花了很长时间才弄清楚,但最终它甚至可以对大量文档进行非常快速的全文搜索。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 中的 Sqlite 全文搜索对非英语字符的 Unicode 支持 的相关文章

  • 居中复选框视图

    如果除了 或代替 复选框之外 您还对单选按钮感兴趣 请参阅this https stackoverflow com questions 16701806 centering views 2而是提问 尽管存在
  • 在Android内存中存储gif图像

    我对安卓还很陌生 我想将图像保存到内存中 然后从内存中检索图像并将其加载到图像视图中 我已使用以下代码成功将图像存储在内存中 void saveImage String fileName img cnt jpg File file new
  • Notification.Builder 中 setGroup() 的用途是什么?

    我对目标的理解有些困难setGroup http developer android com reference android app Notification Builder html setGroup java lang String
  • Android:拍照后调用裁剪活动

    我在解析拍摄照片的 uri 来裁剪活动时遇到问题 在我的应用程序中 用户可以拍摄一张照片或从图库中选择一张照片 然后裁剪并上传 一切听起来都很简单 从图库中选择时 图库应用程序会返回所选照片的 uri 如下所示 content media
  • Android Studio:Android 设备监视器未显示我的设备

    我的真实设备是索尼 Xperia c6502安卓版本4 3 我确定我将其连接到我的计算机然后打开开发者选项 USB调试 on 在 SDK 管理器中 Google USB 驱动程序已安装 I downloaded Xperia Z Drive
  • 调试 Java InterruptedException,即查找原因

    在调试Android应用程序时 有时中断异常发生并使应用程序崩溃 我已经能够在默认异常处理程序上设置断点 但调用堆栈不提供信息 at java util concurrent locks AbstractQueuedSynchronizer
  • 如何将 Google Now 搜索栏添加到我的应用程序中?

    谷歌刚刚将其搜索栏从 Google Now 引入到了 Play 商店应用程序中 如下面的 gif 所示 如何将这个操作栏搜索栏实现到我自己的应用程序中 我想要 style 汉堡动画 从工具栏按钮访问 麦克风按钮 对棒棒糖设备的连锁反应 我已
  • 返回主要活动(意图)时传递数据我做错了什么?

    我是安卓新手 这可能是最简单的问题 但我不明白这里出了什么问题 我试图创建一个通过意图传递值的基本示例 因此 当我关闭第二个活动时 我需要将数据传递到主活动 这是代码 意图测试1 主要活动 public void onClick View
  • 使用 Python 3 动态插入到 sqlite

    我想使用 sqlite 写入多个表 但我不想提前手动指定查询 有数十种可能的排列 例如 def insert sqlite tablename data list global dbc dbc execute insert into tab
  • 以编程方式应用样式资源

    我没有找到一种以编程方式做到这一点的方法 所以我在这里发布这个问题 我也没有找到与此相关的任何问题 我有一个资源样式 在 res values styles xml 中定义 我想做的是使用 java 将这种样式应用到我正在操作的 View
  • 验证假名输入

    我正在开发一个允许用户输入日语字符的应用程序 我试图想出一种方法来确定用户的输入是否是日语假名 平假名 片假名或汉字 应用程序中的某些字段不适合输入拉丁文文本 我需要一种方法将某些字段限制为仅限汉字或仅限片假名等 该项目使用UTF 8编码
  • 在 Android ADT Eclipse 插件中滚动布局编辑器

    有谁知道当布局编辑器的内容溢出一个 屏幕 时如何滚动这些内容 我说的是在设计时使用 ADT 布局编辑器 而不是在物理设备上运行时滚动 效果很好 关闭 Android 布局编辑器中的剪辑 切换剪辑 按钮位于 Android 布局编辑器的右上角
  • 如何在 Android 中保存 Edittext 中的文本而不丢失文本的粗体、斜体等功能

    我想做的就是从 Edittext 中获取文本 该文本具有粗体和斜体等功能 并将其保存在文本文件中 但是当我读回并显示它时 这些功能丢失了 它们不显示 如何通过将文本保存在文本文件或任何文件中来保持丰富的功能 您可以使用Html toHtml
  • 为什么 ExpandableListView 更改 ChildView 设置(Android)?

    我对使用 ExpandableListView 有疑问 就我而言 我有两个组视图和两个子视图 而子视图由一个带有多个按钮 文本视图等的相对布局组成 例如 当首先扩展第二组并对视图持有者进行一些更改并随后扩展第一组时 先前所做的更改也会自动应
  • 如何以编程方式创建 CardView

    我正在开发一个 Android 应用程序Java Android Studio 我想在活动中创建CardView以编程方式 我想将以下属性设置为CardView layout width wrap content layout row 0
  • Android:ANT 构建失败,并显示 google-play-services-lib:“解析为没有项目的 project.properties 文件的路径”

    我正在尝试使用 ANT 构建我的应用程序 但在包含 google play services lib 库项目后 我惨遭失败 Step 1 我在 project properties 文件中设置了对库项目的引用 android library
  • compileReleaseKotlin 失败并出现 java.lang.ClassNotFoundException:com.sun.tools.javac.util.Context

    我正在尝试使用 gradlew 通过终端构建我的 Android 项目 其中包含库模块 在 Android Studio 中 它编译并安装成功 但是当我尝试运行时 gradlew assembleDebug我得到以下堆栈跟踪 Using k
  • Android BLE 扫描永远找不到设备

    几天以来 我尝试在我的应用程序中实现 BLE 连接 我知道我尝试连接的设备功能齐全 因此问题一定是我的代码 我用BluetoothLeScanner startScan 方法 但回调方法永远不会被调用 public void startSc
  • firebase中按范围查询

    我有一个食品价格范围滑块 根据滑块的最小值和最大值 我想显示此范围内的食品 滑块代码 multiSlider setOnThumbValueChangeListener new MultiSlider SimpleChangeListene
  • Android中绑定适配器有什么用?

    我一直在阅读有关Android中绑定适配器的文章 但我似乎不明白它 何时使用绑定适配器 有人可以用一个简单的例子来解释它吗 我读过的一篇文章在主活动中有一个绑定适配器 绑定适配器有一个参数 toastMessage 显然 只要 toastM

随机推荐

  • React Hooks:无法分配给只读属性

    我正在尝试更新使用 React createElement 创建的对象 我试图更新的属性是particleCopy props style top 下面是我的代码 import React useState from react impor
  • 停止将 Chromium 放在前面

    我的测试运行 Puppeteerheadless false模式并打开几个选项卡 如果我在另一个应用程序窗口中 每当它打开一个新选项卡时 它会将 Chromium 聚焦到视图中 这很烦人 有什么办法让它在后台运行吗 我使用的是 macOS
  • 显示函数的完全限定名称

    include
  • 查找最近n天内的所有文档

    My daily集合包含以下文档 date ISODate 2013 01 03T00 00 00Z vid ED san 7046 25 izm 1243 96 date ISODate 2013 01 03T00 00 00Z vid
  • Java + JNA:找不到指定的过程

    我正在尝试使用 Visual Studio 创建一个 dll 文件并在 java 项目中使用 访问它 该库似乎已加载 但总是抛出相同的异常 线程 main 中出现异常 java lang UnsatisfiedLinkError 查找函数
  • 有没有办法在 Visual Studio 项目中创建用户特定的预/后构建事件?

    我目前正在项目中使用构建后事件将程序集复制到另一个目录以进行调试 这是我的机器本地的 仅用于调试目的 所以我更愿意将它放在 中 csproj user文件而不是 csproj文件 我尝试从 复制负责的元素 csproj到 csproj us
  • 方法链接的优点和缺点以及用对象本身替换所有 void 返回参数的可能性

    我最感兴趣的是Java 但我认为这是一个普遍的问题 最近我一直在使用 Arquillian 框架 ShrinkWrap 使用了大量的方法链 方法链的其他示例是以下方法StringBuilder StringBuffer 使用这种方法有明显的
  • onchange 选择框

    假设我们有 2 个不同的选择框 具有相同数量的选项
  • 如何在 jQuery 中使用其中心作为参考点来缩小 div?

    我有以下 div div style margin left 0px height 100px width 100px background color red div 我想使用 jQueryanimate 将 div 缩小到其大小的一半
  • C:epoll和多线程

    我需要创建专门的 HTTP 服务器 为此我计划使用 epoll sycall 但我想利用多个处理器 核心 但我无法提出架构解决方案 ATM我的想法如下 使用自己的epoll描述符创建多个线程 主线程接受连接并将它们分配给线程epoll 但还
  • Java 数组返回奇怪的输出[重复]

    这个问题在这里已经有答案了 我正在为家庭作业问题创建一个方法 该方法返回数组中的最高值 我正在使用一个 for循环将数字输入到数组中 输入代码如下所示 int array new int n for i 0 i
  • 如何在 g++ 中使用不同的 STL

    我想对 g 使用不同的 STL 而不是其默认的 libstdc 做到这一点最简单的方法是什么 我发现 nostdinc 标志禁止 g 查找其 STL 标头 但这只是编译时的事情 它仍然会使 g 链接到它自己的 STL 所以我需要找到一种方法
  • 将二进制文件转换为图像

    我需要找到一种将二进制文件转换为图像的快速方法 二进制文件由 N 个NN 矩阵 我想将 0 与一种颜色关联 将 1 与另一种颜色关联 我需要对超过 1000 个二进制文件执行此操作 如果可能的话 我想避免使用 MatLab 有没有任何工具
  • UITextView突出显示的文本颜色或类似的选项?

    我有一个习惯UITableViewCell with a UILabel and a UITextView in it 我希望当用户突出显示时 这两个文本都显示为白色UITableViewCell 显然设置起来非常简单highlighted
  • 在 C# 中快速加载/读取 TIFF 文件

    我正在编写一个处理 TIFF 图像的 C 应用程序 主要是显示文件 重新排序页面 删除页面 分割多页图像 将单个图像合并为一个多页图像等 我们处理的大多数图像都较小 无论是文件大小还是页码 但也有一些较大的图像 显示图像时 我们需要将多页
  • SSRS 导出到 Excel 创建附加列

    我有一个 SSRS 报告 当我导出到 Excel 时 在 Excel 中查看时会创建不需要的列 确保不创建额外列的最佳方法是什么 我尝试将表行的位置设置为0in 0in但这并没有解决问题 随附的屏幕截图是报告在 Visual Studio
  • 使用 decltype() 声明函数签名

    是否可以声明一个函数bar与函数具有相同的签名foo int foo int a return 0 decltype foo bar return 1 imaginary syntax 我认为这同样适用于 typedef 和别名 您可以使用
  • Oracle SQL:从表中选择数据和分区名称并截断分区

    这是一个由两部分组成的问题 1 是否可以根据数据所在的分区使用 select 语句检索其名称ROWID或者其他一些标识符 eg SELECT DATA ID CATEGORY VALUE PARTITION NAME FROM MYTABL
  • Spring - 捕获bean创建异常

    我想在我的代码中捕获 bean 实例化异常 我有什么选择 一种方法是使用基于 Java 的容器配置 Configuration public class AppConfig Bean public SomeBean someBean try
  • Android 中的 Sqlite 全文搜索对非英语字符的 Unicode 支持

    滚动到末尾以跳过说明 背景 在我的 Android 应用程序中 我想使用非英语 Unicode 文本字符串来搜索存储在 SQLite 数据库中的文本文档 字段中的匹配项 我了解到 所以我认为 我需要做的是实施一个使用 fts3 fts4 进