Jetpack Room
不支持icu
分詞,默認(rèn)分詞對(duì)中文支持很差分歇。不考慮自定義分詞且的情況可以使用WCDB(騰訊開源)状您,且使用方法與Room的使用一致勒叠、入侵性低。
此處介紹的方案和需求主要針對(duì)需要進(jìn)行離線存儲(chǔ)查詢
一膏孟、簡(jiǎn)介
Android端本離線本地分詞主要使用FTS眯分,FTS
版本如下所示,目前使用較多的FTS4
柒桑,Room沒(méi)有對(duì)于FTS5
的支持弊决。
前置知識(shí)點(diǎn):
-
compress
、uncompress
用于支持壓縮和解壓縮 -
content
用于創(chuàng)建無(wú)正文表(只有索引)和外部正文表(正文來(lái)自其他表而非虛表本身)等 -
matchinfo
用于以FTS3
方式存儲(chǔ)FTS4
魁淳,忽略FTS4
額外所需的信息丢氢,但是功能也會(huì)因此受限 -
notindexed
指定某個(gè)列為非索引列 -
prefix
= 額外為指定自己的前綴創(chuàng)建索引 -
tokenizer
:FTS4
提供了四種系統(tǒng)分詞器:simple
、porter
先改、icu
疚察、unicode61
,中文推薦使用icu
tokenizer
分詞:
@Fts4(tokenizer = FtsOptions.TOKENIZER_SIMPLE)
類型 | 描述 |
---|---|
simple | 根據(jù)單詞進(jìn)行分詞仇奶,不區(qū)分大小寫且不支持中文 |
porter | 與simple一樣貌嫡,但是不區(qū)分單詞語(yǔ)義(搜索do時(shí)比驻,能搜索到do、did岛抄、does) |
icu | 將輸入文本根據(jù)ICU規(guī)則尋找單詞邊界和丟棄任何標(biāo)記别惦,支持中文,可拓展(ROOM支持夫椭,建議結(jié)合WCDB 使用) |
unicode61 | 根據(jù)空格和標(biāo)點(diǎn)符號(hào)進(jìn)行分詞掸掸,依賴于Unicode Version 6.1標(biāo)準(zhǔn),支持中文 |
二蹭秋、使用介紹
以下方式為room
使用fts
1扰付、創(chuàng)建FTS
@Fts4(tokenizer = FtsOptions.TOKENIZER_SIMPLE)
@Entity
public class FTS {
public String title;
public FTS(String title) {
this.title = title;
}
}
2、語(yǔ)法介紹
關(guān)于FTS
的增刪改這里就不多介紹了仁讨,與Room操作相同羽莺,這里主要介紹FTS
的查詢中一些特殊點(diǎn),更多使用和介紹可以查看官網(wǎng):FTS
基本查詢:使用
MATCH
洞豁,可以理解為sql語(yǔ)法中的like
SELECT * FROM mail WHERE rowid = 15; -- Fast. Rowid lookup.
SELECT * FROM mail WHERE body MATCH 'sqlite'; -- Fast. Full-text query.
SELECT * FROM mail WHERE mail MATCH 'search'; -- Fast. Full-text query.
SELECT * FROM mail WHERE rowid BETWEEN 15 AND 20; -- Fast. Rowid lookup.
SELECT * FROM mail WHERE subject = 'database'; -- Slow. Linear scan.
SELECT * FROM mail WHERE subject MATCH 'database'; -- Fast. Full-text query.
短語(yǔ)查詢:短語(yǔ)查詢以指定的順序檢索包含指定的術(shù)語(yǔ)集或術(shù)語(yǔ)前綴的所有文檔盐固,而不包含中間標(biāo)記
SELECT * FROM docs WHERE docs MATCH '"linux applications"';
SELECT * FROM docs WHERE docs MATCH '"lin* app*"';
Near查詢
AND
:運(yùn)算符確定兩組文檔的交集
OR
:運(yùn)算符計(jì)算兩組文檔的并集
NOT
:非運(yùn)算符;
3丈挟、示例
創(chuàng)建Dao
刁卜,編寫查詢語(yǔ)句:
@Dao
public interface FTSDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertFTS(FTS fts);
@Query("select * from FTS where title match :query")
List<FTS> queryAll(String query);
//測(cè)試一直返回為空,沒(méi)搞明白原因曙咽,下面可能是原因
//如果在使用“通過(guò)rowid查詢”或“線性掃描”策略的SELECT中使用长酗,則代碼片段都會(huì)返回空字符串
@Query("select snippet(fts, '<b>', '</b>', '...', -1, 15) from fts where title match :query")
List<FTS> queryAllSnippet(String query);
}
創(chuàng)建假數(shù)據(jù):
AppDatabase appDatabase = AppDatabase.getSingleton(this);
for (int i = 0; i < 6000; i++) {
appDatabase.ftsdao().insertFTS(new FTS(i + "Room是安卓中SQLite上的一個(gè)抽象層應(yīng)用框架,可以更輕松桐绒、更好地保存數(shù)據(jù)夺脾。"));
}
執(zhí)行查詢:
long timeMillis = System.currentTimeMillis();
List<FTS> sqLite = appDatabase.ftsdao().queryAll("SQLite");
Log.i(TAG, "查詢數(shù)量: " + sqLite.size());
Log.i(TAG, "時(shí)間: " + (System.currentTimeMillis() - timeMillis));
輸出:
2019-06-23 22:17:04.886 4536-4536/com.active.loser.jetpack I/MainActivity: 查詢數(shù)量: 6000
2019-06-23 22:17:04.887 4536-4536/com.active.loser.jetpack I/MainActivity: 時(shí)間: 74
其他方案:使用
lucene
進(jìn)行本地分詞