背景
我正在对存储在SQLite中的一组电子邮件进行全文搜索,利用其出色的内置FTS4引擎.虽然不完全符合我的预期,但我的查询性能相当差.让我们来看看.
代表架构
我将提供一些有关代码的简化示例,并在适用的地方提供完整代码的链接.
我们有一个MessageTable
存储有关电子邮件消息的数据(完整版本分布在几个文件,这里,这里和这里):
CREATE TABLE MessageTable (
id INTEGER PRIMARY KEY,
internaldate_time_t INTEGER
);
CREATE INDEX MessageTableInternalDateTimeTIndex
ON MessageTable(internaldate_time_t);
Run Code Online (Sandbox Code Playgroud)
可搜索的文本被添加到名为MessageSearchTable
(此处为完整版)的FTS4表中:
CREATE VIRTUAL TABLE MessageSearchTable USING fts4(
id INTEGER PRIMARY KEY,
body
);
Run Code Online (Sandbox Code Playgroud)
该id
搜索表作为一个外键消息表.
我将把它作为练习让读者在这些表格中插入数据(我当然不能透露我的私人电子邮件).我每张桌子的记录不到26k.
问题查询
当我们检索搜索结果时,我们需要按顺序对它们进行排序,internaldate_time_t
这样我们才能获取最新的几个结果.这是一个示例搜索查询(此处为完整版):
SELECT id
FROM MessageSearchTable
JOIN MessageTable USING (id)
WHERE MessageSearchTable MATCH 'a'
ORDER BY internaldate_time_t DESC
LIMIT 10 OFFSET 0
Run Code Online (Sandbox Code Playgroud)
在我的机器上,通过我的电子邮件,运行大约150毫秒,通过以下方式测量:
time …
Run Code Online (Sandbox Code Playgroud) 默认情况下,FTS3/FTS4在python中不起作用(最多2.7).我收到错误:
sqlite3.OperationalError: no such module: fts3要么
sqlite3.OperationalError: no such module: fts4
怎么解决这个问题?
我正在使用FTS查询我的数据库以提高搜索速度,因为我还需要在文本描述中搜索,
当我尝试使用单列进行查询时,其工作正常如下
select * from productsearch where productsearch match ('prod_name:panasonic*tw*')
Run Code Online (Sandbox Code Playgroud)
并且,
select * from productsearch where productsearch match ('prod_short_desc:samsung*s5*')
Run Code Online (Sandbox Code Playgroud)
所以,在两个查询之上给出了我预期的结果,但是当我尝试使用OR
运算符组合两个查询时它没有给我任何结果
select * from productsearch where productsearch match ('prod_name:panasonic*tw* OR
prod_short_desc:samsung*s5*')
Run Code Online (Sandbox Code Playgroud)
所以,我想在使用OR
运算符搜索多个列时知道我在这里做错了什么
UPDATE
以下查询工作正常,但不符合我的要求,
select * from productsearch where productsearch match ('prod_name:panasonic* OR
prod_short_desc:samsung*')
Run Code Online (Sandbox Code Playgroud)
您可以看到,如果我删除多个令牌,那么它也可以与OR
运算符一起正常工作.
我正在尝试构建一个使用SQLite FTS的应用程序.我发现了一篇关于如何按照我想要的方式做到这一点的非常有趣的帖子.但是,我根本不是一个非常有经验的程序员,特别是在本文中使用的CoreData中.是否有任何示例项目与本文中描述的内容类似?看看在上下文中做了什么,这对我有很大的帮助.我很抱歉,如果这是一个愚蠢的问题,我对这一切仍然是如此新鲜.感谢您的帮助!
以下是该文章的链接:http://blog.lunatech.com/2013/01/24/ios-core-data-sqlite-full-text-search
我正在尝试使用不受信任的用户输入执行 SQLite FTS 查询。我不想让用户访问查询语法,也就是说他们将无法执行像foo OR bar AND cats
. 如果他们尝试使用该字符串进行查询,我想将其解释为更像foo \OR bar \AND cats
.
SQLite 似乎没有为此内置任何内容,因此我可能最终会构建自己的转义函数,但这似乎很危险且容易出错。有没有首选的方法来做到这一点?
假设搜索输入是“是什么”。这将匹配“无论它是什么”以及“什么是”,这是确切的短语。现在,如何在排序中将准确的短语排在第一位?
从昨天开始我就一直在思考这个问题,并且不断提出不同的解决方案,但每个解决方案都有其自身的缺陷。
这是我失败的方法(假设输入=“是什么”):
SELECT snippet(fts), 1 as rank
FROM fts
WHERE body MATCH '"what is"'
UNION ALL
SELECT snippet(fts), 2 as rank
FROM fts
WHERE body MATCH 'what* NEAR/3 is*' -- 3 is arbitrary
ORDER BY rank
Run Code Online (Sandbox Code Playgroud)
这是我当前的解决方案:
SELECT snippet(fts)
FROM fts WHERE rowId IN
(
SELECT DISTINCT rowId
FROM
(
SELECT rowId, 1 as rank
FROM fts
WHERE body MATCH '"what …
Run Code Online (Sandbox Code Playgroud) SQLite FTS 的文档暗示应该使用 INSERT、UPDATE、DELETE 等填充和更新 FTS 表。
这就是我正在做的 - 添加行,删除它们等,但最近我注意到,一旦我创建了 FTS 表,它就会使用源中的数据自动填充。我是这样创建的:
CREATE VIRTUAL TABLE notes_fts USING fts4(content="notes", notindexed="id", id, title, body)
Run Code Online (Sandbox Code Playgroud)
如果我在“notes”表中添加一行,它也会自动添加到notes_fts。我想这就是虚拟表。
但是,为什么有一章是关于填充 FTS 表的呢?甚至有什么意义,因为例如,如果我删除一行,如果它仍在源表中,它就会回来。
对此有什么想法吗?FTS 真的需要填充吗?
我有一个Android应用程序,它使用FTS4虚拟表在SQLite数据库中搜索数据.它工作正常,但当表中的数据包含特殊字符(如'á','é','í','ó','ú'或'ñ')时,SQLite MATCH函数不会产生任何结果.我此时迷路了.谢谢.
我已经下载了最新的 SQLite 3.7.15.2 shell (Win32) 并尝试完全按照http://sqlite.org/fts3.html#section_3上写的那样执行 FTS 示例之一
-- Virtual table declaration
CREATE VIRTUAL TABLE docs USING fts3();
-- Virtual table data
INSERT INTO docs(docid, content) VALUES(1, 'a database is a software system');
INSERT INTO docs(docid, content) VALUES(2, 'sqlite is a software system');
INSERT INTO docs(docid, content) VALUES(3, 'sqlite is a database');
-- Return the set of documents that contain the term "sqlite", and the
-- term "database". This query will return the document with docid 3 only. …
Run Code Online (Sandbox Code Playgroud) 问题是查询返回除“ id”以外的所有列
我使用fts4,并在文档中说:
启用了FTS的表始终使用INTEGER类型的主键,并且其列名称为“ rowid”。如果您的FTS表支持的实体定义了主键,则它必须使用该类型和列名。
这是我的实体类:
@Fts4
@Entity(tableName = "projects")
public class Project {
@ColumnInfo(name = "rowid")
@PrimaryKey(autoGenerate = true)
private int id;
private String name;
@ColumnInfo(name = "start_date")
private String startDate;
@ColumnInfo(name = "end_date")
private String endDate;
private String description;
@ColumnInfo(name = "icon_path")
private String iconPath;
private long budget;
public Project(String name, String startDate, String endDate, String description, String iconPath, long budget) {
this.name = name;
this.startDate = startDate;
this.endDate = endDate;
this.description = description;
this.iconPath = iconPath;
this.budget …
Run Code Online (Sandbox Code Playgroud)