android - 如何在我的 DAO 中引用可搜索的 FTS4 表而不出现编译器错误?

标签 android sqlite full-text-search android-room fts4

android 的 android [FTS4 文档][1] 指出“此类将在数据库中有一个映射 SQLite FTS4 表”。我应该将其解释为只需添加注释即可生成映射 SQLite FTS4 表,还是意味着我需要提供某种映射表以将 FTS4 实体类“连接”到虚拟 FTS4 表?

我目前假设是前者。如果那是正确的,那么我如何实际使用这个映射表呢?我认为这样说是正确的,当您使用 FTS4 注释创建一个实体时,它会生成一个普通表和一个映射表,这两者实际上都不是可以使用 MATCH 函数查询的虚拟 FTS4 表。那么映射表到底映射到什么?!一些在运行时(可能在数据库回调或迁移期间)实现的假设虚拟 FTS4 外部内容表?在那种情况下,我应该如何在我的 DAO 中引用可搜索的 FTS4 表而不出现编译器错误?

已解决:

事实证明,之前的解释是正确的,生成的映射表包含了全文搜索所需的虚拟表。我仍然认为文档在这方面可以更清楚,但最终真正的根本问题是我的房间依赖性不是最新的。哦!

最佳答案

使用 FTS 3 或 4,您可以定义核心表,然后使用 USING 关键字和适当的参数(诸如 FTS3 或 FTS4 之类的模块以及模块需要的参数)定义 VIRTUAL 表。然后 FTS 模块生成表格。

例如一个数据库有一个标准的圣经表,列有书籍文本、章节整数、诗句整数和内容文本。对于 FTS,您可以使用类似

的方式创建虚拟表
CREATE VIRTUAL TABLE bible_fts USING fts3(book,chapter INTEGER, verse INTEGER, content TEXT)
  • 这是唯一的特殊表,下面的表是 FTS 模块创建的普通表。

当执行 CREATE 语句时,将创建表 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!

我的理解是您必须定义核心表。

您编写相关的@FTS(3 或 4)注解 Room 生成虚拟表,例如你得到一些类似的东西:-

    _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')");
  • 附言使用 Room,生成的代码几乎就是房间圣经。
  • 上面的方法行不通,因为我只放置了@FTS3 和任何旧表(有限制)。我这样做只是为了演示。

然后我相信因为 Dao 的 etc 引用了他们需要的注释。但是,我怀疑您必须经常对@Ignore 进行编码。 (我从来没有真正使用过 FTS,我的经验是使用一个工具,我正在玩一个工具,将非房间数据库转换为房间,并使转换与 FTS 一起工作,即到 Room 明智地接受数据库模式的阶段)。

您还可以找到 Enabling SQLite FTS in Room 2.1的用途。

例子

核心表

实体 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);

}

数据库

数据库.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 - 如何在我的 DAO 中引用可搜索的 FTS4 表而不出现编译器错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58351266/

相关文章:

postgresql 全文接近度 (`<->` ) 搜索 json 文档

android - 在android中创建一个依赖库

java - 如何解码Java字符串中的unicode char?

sql - 计算每列值的频率,显示所有填充空白的列的结果

SQLite 查询仅匹配多行或相同 ID

python - 获取相对于执行的 Flask 应用程序的路径

mysql - 关于 sphinx 段规则

安卓全文搜索

android - 升级到 FirebaseUI 3.0 后无法使用 FirebaseRecyclerOptions 检索数据

android - 从另一个 Activity 中获取数据