Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android中的全文搜索示例_Android_Sqlite_Full Text Search - Fatal编程技术网

Android中的全文搜索示例

Android中的全文搜索示例,android,sqlite,full-text-search,Android,Sqlite,Full Text Search,我很难理解如何在Android上使用全文搜索(FTS)。我读过这本书。我知道。然而,我很难找到任何我能理解的例子 基本数据库模型 SQLite数据库表(名为example\u table)有4列。但是,只有一列(名为text\u column)需要为全文搜索编制索引。text\u列的每一行包含长度从0到1000个单词不等的文本。总行数大于10000 您将如何设置表和/或FTS虚拟表 您将如何对text\u列执行FTS查询 附加说明: 因为只需要索引一列,所以只需要使用FTS表(并删除exa

我很难理解如何在Android上使用全文搜索(FTS)。我读过这本书。我知道。然而,我很难找到任何我能理解的例子

基本数据库模型 SQLite数据库表(名为
example\u table
)有4列。但是,只有一列(名为
text\u column
)需要为全文搜索编制索引。
text\u列的每一行
包含长度从0到1000个单词不等的文本。总行数大于10000

  • 您将如何设置表和/或FTS虚拟表
  • 您将如何对
    text\u列
    执行FTS查询
附加说明:

  • 因为只需要索引一列,所以只需要使用FTS表(并删除
    example_table
  • 对于如此大的表,不希望在FTS表中存储重复的
    text\u列
    。建议使用
  • 外部内容表使用FTS4,但FTS4是。答案可以假设API>=11,但对支持较低版本的选项进行评论会有所帮助
  • 更改原始表中的数据不会自动更新FTS表(反之亦然)。对于这个基本示例,在您的答案中包含这些内容并不是必需的,但会有所帮助
最基本的答案 我正在使用下面的普通sql,以便所有内容都尽可能清晰易读。在您的项目中,您可以使用Android便利方法。下面使用的
db
对象是的一个实例

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

使用或比使用execSQL更好

你也可以使用这个方法。注意
MATCH
关键字

更全面的回答 上面的虚拟FTS表有问题。每个列都被索引,但如果某些列不需要索引,这将浪费空间和资源。唯一需要FTS索引的列可能是
text\u列

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

创建表格

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)");
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.')");
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_example_table WHERE fts_example_table MATCH ?", selectionArgs);
请注意,我们必须使用FTS4而不是FTS3来实现这一点。API版本11之前的Android不支持FTS4。您可以(1)只为API>=11提供搜索功能,或者(2)使用FTS3表(但这意味着数据库将更大,因为两个数据库中都存在全文列)

填充表格

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)");
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.')");
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_example_table WHERE fts_example_table MATCH ?", selectionArgs);
(同样,do INSERT中有比使用
execSQL
更好的方法。我只是出于可读性而使用它。)

如果您现在尝试在
FTS\u example\u表
上执行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')");
这将重建整个表。不过,这可能会很慢,所以在每一个小小的改变之后,你都不想做这件事。您将在完成外部内容表上的所有插入后执行此操作。如果确实需要自动保持数据库同步,可以使用。然后向下滚动一点以找到方向

查询数据库

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)");
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.')");
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_example_table WHERE fts_example_table MATCH ?", selectionArgs);
这与以前相同,只是这次您只能访问
text\u列
(和
docid
)。如果需要从外部内容表中的其他列获取数据,该怎么办?由于FTS表的
docid
与外部内容表的
rowid
(在本例中为
\u id
)匹配,因此可以使用联接。(感谢您的帮助。)

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

  • (SQLite文档)
  • (安卓文档)
附加说明
  • SQLite FTS查询中的Set运算符(AND、OR、NOT)具有AND。不幸的是,Android显然不支持增强的查询语法(请参阅、和)。这意味着混合和/或变得困难(似乎需要使用或检查)。非常不幸。如果此区域有更新,请添加注释
在使用中的内容重建fts表时,不要忘记


我在更新、插入、删除时触发了一个记录良好的问题,我是在反对你在这里的任意否决票。事实上,如果你以你指定的方式使用fts表(从非fts表中选择,其中_id包含在fts表匹配返回的docid集合中),你可以使用content=“”来节省空间。这将在不复制内容的情况下创建全文索引。See FTS4内容选项的添加时间不早于SQLite 3.7.9(),这意味着它在Android API 16之前不可用。SQLiteDatabase将引发使用尝试。如何通过此查询获得半个单词的匹配?@HiteshDanidhariya,这不是进行部分单词匹配吗?对不起,我已经有一段时间没有做这个了,但我认为它已经做了。@suragch得到了解决方案。必须在搜索字符串后添加“*”,谢谢。你的回答对我帮助很大。:)<代码>插入到foo_fts值(“重建”)