如何在我的 DAO 中引用可搜索的 FTS4 table 而不会出现编译器错误?
How can I reference a searchable FTS4 table in my DAO without getting a compiler error?
android [FTS4 文档][1] android 声明 "This class will have a mapping SQLite FTS4 table in the database"。我应该将其解释为映射 SQLite FTS4 table 将仅通过添加注释生成,还是意味着我需要提供某种映射 table 到 'wire up' FTS4 实体 class 到虚拟 FTS4 table?
我目前假设是前者。如果那是正确的,那么我如何实际使用此映射 table 呢?我认为这样说是正确的,当你创建一个带有 FTS4 注释的实体时,它会生成一个普通的 table 和一个映射 table,这两者实际上都不是虚拟的 FTS4 table,它可以是使用 MATCH 函数查询。那么映射table到底映射到什么?!一些假设的虚拟 FTS4 外部内容 table 在运行时实现,可能是在数据库回调或迁移期间?在那种情况下,我应该如何在我的 DAO 中引用可搜索的 FTS4 table 而不会出现编译器错误?
已解决:
原来之前的解释是正确的,生成的映射 table 包括全文搜索所需的虚拟 table。我仍然认为文档在这方面可以更清楚,但最终真正的根本问题是我的房间依赖性不是最新的。哦!
对于 FTS 3 或 4,您可以定义核心 table,然后使用 USING 关键字和适当的参数(模块,例如 FTS3 或 FTS4,以及模块需要的参数)定义 VIRTUAL table ).然后 FTS 模块生成 tables.
例如一个数据库有一本标准的圣经 table,包含书籍 TEXT、章节 INTEGER、诗句 INTEGER 和内容 TEXT 列。对于 FTS,您使用
之类的东西创建虚拟 table
CREATE VIRTUAL TABLE bible_fts USING fts3(book,chapter INTEGER, verse INTEGER, content TEXT)
- 这是唯一特殊的 table,下面的 table 是正常的 table 除了 FTS 模块创建它们之外。
当执行 CREATE 语句时,会创建 table bible_fts_content、bible_fts_segments 和 bible_fts_segdir。 (对于 FTS4 可能略有不同)。然后,SQLite 的 FTS 就绪版本将能够处理诸如 MATCH 之类的事情。
总之,全靠定义模块的特殊处理。
In case you couldn't tell, it's very unclear to me what my responsibilties are here!
我的理解是你必须定义核心tables。
您编写相关的@FTS(3 或 4)注解 Room 生成 vritual table 例如你得到一些类似的东西:-
_db.execSQL("CREATE TABLE IF NOT EXISTS `device_item` (`id` INTEGER, `initial` TEXT, `added1` INTEGER NOT NULL DEFAULT 0, `added2` TEXT DEFAULT '', PRIMARY KEY(`id`))");
_db.execSQL("CREATE VIRTUAL TABLE IF NOT EXISTS `table1` USING FTS3(`name` TEXT, `mapToTable2` INTEGER NOT NULL, `mapToTable3` INTEGER NOT NULL)");
_db.execSQL("CREATE TABLE IF NOT EXISTS `table2` (`id` INTEGER, `nameOfT2` TEXT, `anotherNameOfT2` TEXT, PRIMARY KEY(`id`))");
_db.execSQL("CREATE TABLE IF NOT EXISTS `table3` (`id` INTEGER, `nameOfT3` TEXT, `anotherNameOfT3` TEXT, PRIMARY KEY(`id`))");
_db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
_db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '91a23aea1ab6e684828fad82668cb9a5')");
- P.S。使用 Room,生成的代码几乎就是房间圣经。
- 上面的方法不起作用,因为我只输入了@FTS3 和任何旧的table(有限制)。我只是为了演示。
然后我相信因为Dao的etc引用了他们需要的注解。但是,我怀疑您必须经常对@Ignore 进行编码。 (我从来没有真正使用过 FTS,我的经验是使用一个工具,我正在玩一个工具,将非房间数据库转换为房间,并使转换与 FTS 一起工作,即到 Room 明智地接受数据库模式的阶段)。
您可能还会发现 Enabling SQLite FTS in Room 2.1 有用。
例子
核心table
实体Bible.java
@Entity(tableName = "bible")
public class Bible {
@PrimaryKey
Long id;
String book;
Long chapter;
Long verse;
String content;
public Bible(){}
@Ignore
public Bible(String bookName, Long chapter, Long verse, String content) {
this.book = bookName;
this.chapter = chapter;
this.verse = verse;
this.content = content;
}
// ...... getters and setters nothing special
}
FTS实体
由于书籍和内容是文本列,因此将为 FTS 定义这些列
BibleFTS.java
@Fts4(contentEntity = Bible.class) //<<<<<<<<<< the table to FTSalise
@Entity(tableName = "bible_fts")
public class BibleFTS {
@PrimaryKey
Long rowid; //<<<<<<<<<< MUST HAVE
String book;
String content;
}
- 不确定是否需要 getter 和 setter,第一次尝试没有
- 不确定自动生成的影响(但 Long 不需要 @NonNull 不自动生成)
道
BibleDao.java(涵盖圣经和 BibleFTS)
@Dao
public interface BibleDao {
@Insert
Long insertBibleRow(Bible bible);
@Insert
Long[] insertBibleRows(Bible... bibles);
@Query("SELECT * FROM bible")
List<Bible> getAllBibleRows();
//<<<<<<<<<< USED TO REBUILD (Room might do this anyway think I saw it somewhere) >>>>>>>>>>
@Query("INSERT INTO bible_fts(bible_fts) VALUES('rebuild')")
void rebuild();
//<<<<<<<<<< SEARCH The searchable columns >>>>>>>>>
@Query("SELECT bible.book,bible.chapter,bible.verse,bible.content FROM bible_fts JOIN bible ON id = docid WHERE bible_fts MATCH :searchFor")
List<Bible> searchFor(String searchFor);
}
数据库
Database.java
@androidx.room.Database(
version = 1,
entities = {
Bible.class, //<<<<<<<<<<
BibleFTS.class //<<<<<<<<<<
})
abstract class Database extends RoomDatabase {
abstract BibleDao bibleDao(); //<<<<<<<<<<
}
测试Activity
MainActivity.java(onCreate 方法)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDatabase = Room.databaseBuilder(this,Database.class,"devicitems")
.allowMainThreadQueries()
.build();
mBibleDao = mDatabase.bibleDao();
Bible b = new Bible("Geneisis",1L,1L,"In the begining some bright spark made a thinngy called Earth and said I shall rule over that little speck.");
mBibleDao.insertBibleRow(b);
mBibleDao.rebuild();
List<Bible> found = mBibleDao.searchFor("in");
for (Bible currentBible: found) {
Log.d(
"FOUNDIN",
"Found in in :- Book" + currentBible.getBook() +
" - Chapter " + currentBible.getChapter() +
" - Verse " + currentBible.getVerse() +
"\n\t" + currentBible.getContent()
);
}
}
结果
2019-10-12 21:37:00.584 30255-30255/? D/FOUNDIN: Found in in :- BookGeneisis - Chapter 1 - Verse 1
In the begining some bright spark made a thinngy called Earth and said I shall rule over that little speck.
android [FTS4 文档][1] android 声明 "This class will have a mapping SQLite FTS4 table in the database"。我应该将其解释为映射 SQLite FTS4 table 将仅通过添加注释生成,还是意味着我需要提供某种映射 table 到 'wire up' FTS4 实体 class 到虚拟 FTS4 table?
我目前假设是前者。如果那是正确的,那么我如何实际使用此映射 table 呢?我认为这样说是正确的,当你创建一个带有 FTS4 注释的实体时,它会生成一个普通的 table 和一个映射 table,这两者实际上都不是虚拟的 FTS4 table,它可以是使用 MATCH 函数查询。那么映射table到底映射到什么?!一些假设的虚拟 FTS4 外部内容 table 在运行时实现,可能是在数据库回调或迁移期间?在那种情况下,我应该如何在我的 DAO 中引用可搜索的 FTS4 table 而不会出现编译器错误?
已解决:
原来之前的解释是正确的,生成的映射 table 包括全文搜索所需的虚拟 table。我仍然认为文档在这方面可以更清楚,但最终真正的根本问题是我的房间依赖性不是最新的。哦!
对于 FTS 3 或 4,您可以定义核心 table,然后使用 USING 关键字和适当的参数(模块,例如 FTS3 或 FTS4,以及模块需要的参数)定义 VIRTUAL table ).然后 FTS 模块生成 tables.
例如一个数据库有一本标准的圣经 table,包含书籍 TEXT、章节 INTEGER、诗句 INTEGER 和内容 TEXT 列。对于 FTS,您使用
之类的东西创建虚拟 tableCREATE VIRTUAL TABLE bible_fts USING fts3(book,chapter INTEGER, verse INTEGER, content TEXT)
- 这是唯一特殊的 table,下面的 table 是正常的 table 除了 FTS 模块创建它们之外。
当执行 CREATE 语句时,会创建 table bible_fts_content、bible_fts_segments 和 bible_fts_segdir。 (对于 FTS4 可能略有不同)。然后,SQLite 的 FTS 就绪版本将能够处理诸如 MATCH 之类的事情。
总之,全靠定义模块的特殊处理。
In case you couldn't tell, it's very unclear to me what my responsibilties are here!
我的理解是你必须定义核心tables。
您编写相关的@FTS(3 或 4)注解 Room 生成 vritual table 例如你得到一些类似的东西:-
_db.execSQL("CREATE TABLE IF NOT EXISTS `device_item` (`id` INTEGER, `initial` TEXT, `added1` INTEGER NOT NULL DEFAULT 0, `added2` TEXT DEFAULT '', PRIMARY KEY(`id`))");
_db.execSQL("CREATE VIRTUAL TABLE IF NOT EXISTS `table1` USING FTS3(`name` TEXT, `mapToTable2` INTEGER NOT NULL, `mapToTable3` INTEGER NOT NULL)");
_db.execSQL("CREATE TABLE IF NOT EXISTS `table2` (`id` INTEGER, `nameOfT2` TEXT, `anotherNameOfT2` TEXT, PRIMARY KEY(`id`))");
_db.execSQL("CREATE TABLE IF NOT EXISTS `table3` (`id` INTEGER, `nameOfT3` TEXT, `anotherNameOfT3` TEXT, PRIMARY KEY(`id`))");
_db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
_db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '91a23aea1ab6e684828fad82668cb9a5')");
- P.S。使用 Room,生成的代码几乎就是房间圣经。
- 上面的方法不起作用,因为我只输入了@FTS3 和任何旧的table(有限制)。我只是为了演示。
然后我相信因为Dao的etc引用了他们需要的注解。但是,我怀疑您必须经常对@Ignore 进行编码。 (我从来没有真正使用过 FTS,我的经验是使用一个工具,我正在玩一个工具,将非房间数据库转换为房间,并使转换与 FTS 一起工作,即到 Room 明智地接受数据库模式的阶段)。
您可能还会发现 Enabling SQLite FTS in Room 2.1 有用。
例子
核心table
实体Bible.java
@Entity(tableName = "bible")
public class Bible {
@PrimaryKey
Long id;
String book;
Long chapter;
Long verse;
String content;
public Bible(){}
@Ignore
public Bible(String bookName, Long chapter, Long verse, String content) {
this.book = bookName;
this.chapter = chapter;
this.verse = verse;
this.content = content;
}
// ...... getters and setters nothing special
}
FTS实体
由于书籍和内容是文本列,因此将为 FTS 定义这些列
BibleFTS.java
@Fts4(contentEntity = Bible.class) //<<<<<<<<<< the table to FTSalise
@Entity(tableName = "bible_fts")
public class BibleFTS {
@PrimaryKey
Long rowid; //<<<<<<<<<< MUST HAVE
String book;
String content;
}
- 不确定是否需要 getter 和 setter,第一次尝试没有
- 不确定自动生成的影响(但 Long 不需要 @NonNull 不自动生成)
道
BibleDao.java(涵盖圣经和 BibleFTS)
@Dao
public interface BibleDao {
@Insert
Long insertBibleRow(Bible bible);
@Insert
Long[] insertBibleRows(Bible... bibles);
@Query("SELECT * FROM bible")
List<Bible> getAllBibleRows();
//<<<<<<<<<< USED TO REBUILD (Room might do this anyway think I saw it somewhere) >>>>>>>>>>
@Query("INSERT INTO bible_fts(bible_fts) VALUES('rebuild')")
void rebuild();
//<<<<<<<<<< SEARCH The searchable columns >>>>>>>>>
@Query("SELECT bible.book,bible.chapter,bible.verse,bible.content FROM bible_fts JOIN bible ON id = docid WHERE bible_fts MATCH :searchFor")
List<Bible> searchFor(String searchFor);
}
数据库
Database.java
@androidx.room.Database(
version = 1,
entities = {
Bible.class, //<<<<<<<<<<
BibleFTS.class //<<<<<<<<<<
})
abstract class Database extends RoomDatabase {
abstract BibleDao bibleDao(); //<<<<<<<<<<
}
测试Activity
MainActivity.java(onCreate 方法)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDatabase = Room.databaseBuilder(this,Database.class,"devicitems")
.allowMainThreadQueries()
.build();
mBibleDao = mDatabase.bibleDao();
Bible b = new Bible("Geneisis",1L,1L,"In the begining some bright spark made a thinngy called Earth and said I shall rule over that little speck.");
mBibleDao.insertBibleRow(b);
mBibleDao.rebuild();
List<Bible> found = mBibleDao.searchFor("in");
for (Bible currentBible: found) {
Log.d(
"FOUNDIN",
"Found in in :- Book" + currentBible.getBook() +
" - Chapter " + currentBible.getChapter() +
" - Verse " + currentBible.getVerse() +
"\n\t" + currentBible.getContent()
);
}
}
结果
2019-10-12 21:37:00.584 30255-30255/? D/FOUNDIN: Found in in :- BookGeneisis - Chapter 1 - Verse 1
In the begining some bright spark made a thinngy called Earth and said I shall rule over that little speck.