gpt4 book ai didi

android - Android中的全文搜索示例

转载 作者:IT老高 更新时间:2023-10-28 13:08:45 27 4
gpt4 key购买 nike

我很难理解如何在 Android 中使用全文搜索 (FTS)。我已阅读 SQLite documentation on the FTS3 and FTS4 extensions .我知道it's possible to do on Android .但是,我很难找到任何我能理解的例子。

基本数据库模型

一个 SQLite 数据库表(名为 example_table)有 4 列。但是,只有一列(名为 text_column)需要为全文搜索建立索引。 text_column 的每一行都包含长度从 0 到 1000 个字不等的文本。总行数大于 10,000。

  • 您将如何设置表和/或 FTS 虚拟表?
  • 您将如何对 text_column 执行 FTS 查询?

补充说明:

  • 因为只需要索引一列,所以只使用 FTS 表(并删除 example_table)将是 inefficient for non-FTS queries .
  • 对于如此大的表,不希望在 FTS 表中存储重复的 text_column 条目。 This post建议使用 external content table .
  • 外部内容表使用 FTS4,但 FTS4 为 not supported before Android API 11 .答案可以假设 API >= 11,但评论支持较低版本的选项会很有帮助。
  • 更改原始表中的数据不会自动更新 FTS 表(反之亦然)。其中triggers对于这个基本示例,您的答案不是必需的,但仍然会有所帮助。

最佳答案

最基本的答案

我使用下面的普通 sql,以便一切都尽可能清晰易读。在您的项目中,您可以使用 Android 便捷方法。下面使用的 db 对象是 SQLiteDatabase 的一个实例.

Create FTS Table

db.execSQL("CREATE VIRTUAL TABLE fts_table USING fts3 ( col_1, col_2, text_column )");

这可以放在扩展的 SQLiteOpenHelper 类的 onCreate() 方法中。

Populate FTS Table

db.execSQL("INSERT INTO fts_table VALUES ('3', 'apple', 'Hello. How are you?')");
db.execSQL("INSERT INTO fts_table VALUES ('24', 'car', 'Fine. Thank you.')");
db.execSQL("INSERT INTO fts_table VALUES ('13', 'book', 'This is an example.')");

最好使用SQLiteDatabase#insertprepared statementsexecSQL.

Query FTS Table

String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_table WHERE fts_table MATCH ?", selectionArgs);

您也可以使用 SQLiteDatabase#query方法。注意 MATCH 关键字。

更完整的答案

上面的虚拟 FTS 表有问题。每列都有索引,但是如果某些列不需要索引,这是浪费空间和资源。唯一需要 FTS 索引的列可能是 text_column

为了解决这个问题,我们将使用常规表和虚拟 FTS 表的组合。 FTS 表将包含索引,但不包含常规表中的实际数据。相反,它将有一个指向常规表内容的链接。这称为 external content table .

enter image description here

创建表格

db.execSQL("CREATE TABLE example_table (_id INTEGER PRIMARY KEY, col_1 INTEGER, col_2 TEXT, text_column TEXT)");
db.execSQL("CREATE VIRTUAL TABLE fts_example_table USING fts4 (content='example_table', text_column)");

请注意,我们必须使用 FTS4 而不是 FTS3 来执行此操作。 API 版本 11 之前的 Android 不支持 FTS4。您可以 (1) 仅提供 API >= 11 的搜索功能,或 (2) 使用 FTS3 表(但这意味着数据库会更大,因为存在全文列在两个数据库中)。

填充表格

db.execSQL("INSERT INTO example_table (col_1, col_2, text_column) VALUES ('3', 'apple', 'Hello. How are you?')");
db.execSQL("INSERT INTO example_table (col_1, col_2, text_column) VALUES ('24', 'car', 'Fine. Thank you.')");
db.execSQL("INSERT INTO example_table (col_1, col_2, text_column) VALUES ('13', 'book', 'This is an example.')");

(同样,在执行插入时有比使用 execSQL 更好的方法。我只是为了它的可读性而使用它。)

如果您现在尝试在 fts_example_table 上执行 FTS 查询,您将得不到任何结果。原因是更改一张表不会自动更改另一张表。您必须手动更新 FTS 表:

db.execSQL("INSERT INTO fts_example_table (docid, text_column) SELECT _id, text_column FROM example_table");

(docid 类似于常规表的 rowid。)您必须确保每次更新 FTS 表(以便它可以更新索引)对外部内容表进行更改(插入、删除、更新)的时间。这会变得很麻烦。如果你只是制作一个预填充的数据库,你可以这样做

db.execSQL("INSERT INTO fts_example_table(fts_example_table) VALUES('rebuild')");

这将重建整个表。不过,这可能会很慢,所以这不是您在每次小改动后都想做的事情。您将在完成外部内容表上的所有插入后执行此操作。如果确实需要自动保持数据库同步,可以使用 triggers . Go here并向下滚动一点以查找路线。

查询数据库

String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_example_table WHERE fts_example_table MATCH ?", selectionArgs);

这和以前一样,只是这次您只能访问 text_column(和 docid)。如果您需要从外部内容表中的其他列获取数据怎么办?由于 FTS 表的 docid 与外部内容表的 rowid(在本例中为 _id)匹配,因此您可以使用连接。 (感谢 this answer 的帮助。)

String sql = "SELECT * FROM example_table WHERE _id IN " +
"(SELECT docid FROM fts_example_table WHERE fts_example_table MATCH ?)";
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery(sql, selectionArgs);

进一步阅读

仔细阅读这些文档,了解使用 FTS 虚拟表的其他方法:

附加说明

关于android - Android中的全文搜索示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29815248/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com