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

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

解决了:

事实证明,前一种解释是正确的,生成的映射表包括全文搜索所需的虚拟表。我仍然认为文档可以更清楚地说明这一点,但最终真正的潜在问题是我的房间依赖不是最新的。哦!

最佳答案

使用 FTS 3 或 4,您定义核心表,然后使用 USING 关键字和适当的参数(模块,如 FTS3 或 FTS4 以及模块期望的参数)定义虚拟表。 FTS 模块然后生成表格。

例如。一个数据库有一个标准的圣经表,有列 book TEXT、chapter INTEGER、verse INTEGER 和 content TEXT。对于 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 之类的事情。

    简而言之,这完全取决于定义模块的特殊处理。
  • The Virtual Table Mechanism Of SQLite
  • SQLite FTS3 and FTS4 Extensions



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

    您编码相关的@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')");
    
  • P.S.使用 Room 生成的代码实际上是房间圣经。
  • 以上不起作用,因为我只是把@FTS3 和任何旧表(有限制)。我只是为了演示。

  • 然后我相信因为Dao's 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 实体

    由于 book 和 content 是文本列,这些将为 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 - 如何在 DAO 中引用可搜索的 FTS4 表而不会出现编译器错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58351266/

    10-10 09:44