Документация Kotlin androidx.room.fts4 выглядит так, как будто она написана с использованием Java! Кто-нибудь реализовал сущность fts4 с использованием Kotlin? - PullRequest
0 голосов
/ 08 октября 2019

У меня возникли трудности с реализацией fts4 в мое приложение. Моя цель - создать приложение полностью на Kotlin, используя новейшие компоненты Jetpack, включая базу данных Room. Тем не менее, когда я посмотрел документацию для fts4, примеры были написаны на Java!

Кроме документации по android для связанных классов и документации sqlite для fts3 / 4 , Я просмотрел несколько разных уроков по этому вопросу. Примечательно, что этот блог пост и эти слайды . Все учебники, которые я смог найти до сих пор, были написаны на Java и основаны на миграциях баз данных для создания виртуальной таблицы, необходимой для fts ^ (СМ. НИЖЕ, НИЖЕ). Несмотря на это, мне еще предстоит собрать воедино рабочее решение.

Вот последняя итерация моего кода:

Entity:


@Entity(tableName = "items")

data class Item(
    @PrimaryKey 
    @ColumnInfo(name = "rowid")
    val rowId: Int,
    val qualities: String,
    val itemId: String,
    val name: String,
    val description: String,
    val quantity: Int,

) {
    override fun toString() = name
}

FTS Entity:

@Entity(tableName = "items_fts")
@Fts4(contentEntity = Item::class, tokenizer = FtsOptions.TOKENIZER_PORTER)

data class ItemFTS(
    @PrimaryKey
    @ColumnInfo(name = "rowid")
    val id: Int,
    val qualities: String
) {
    override fun toString() = items
}

База данных номеров:

@Database(entities = [Item::class, ItemFTS::class], version = 1, exportSchema = false)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
    abstract fun itemDao(): ItemDao

    companion object {

        // For Singleton instantiation
        @Volatile private var instance: AppDatabase? = null

        fun getInstance(context: Context): AppDatabase {
            return instance ?: synchronized(this) {
                instance ?: buildDatabase(context).also { instance = it }
            }
        }

        // Create and pre-populate the database.
        private fun buildDatabase(context: Context): AppDatabase {
            return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
                .addCallback(object : RoomDatabase.Callback() {
                    override fun onCreate(db: SupportSQLiteDatabase) {
                        super.onCreate(db)
                        val request = OneTimeWorkRequestBuilder<SeedDatabaseWorker>().build()
                        WorkManager.getInstance().enqueue(request)
                    }
                })
// **I tried adding in migrations here based on the blog posts attached to this stack overflow 
// question but didn't seem to work, even when I incremented the database version.**
                .build()
        }
    }
}

Работник базы данных семян:

class SeedDatabaseWorker(
    context: Context,
    workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {

    private val TAG by lazy { SeedDatabaseWorker::class.java.simpleName }

    override suspend fun doWork(): Result = coroutineScope {

        try {
            applicationContext.assets.open(ITEM_DATA_FILENAME).use { inputStream ->
                JsonReader(inputStream.reader()).use { jsonReader ->
                    val itemType = object : TypeToken<List<Item>>() {}.type
                    val itemList: List<Item> = Gson().fromJson(jsonReader, itemType)

                    val database = AppDatabase.getInstance(applicationContext)
                    database.itemDao().insertAll(itemList)

                    Result.success()
                }
            }
        } catch (ex: Exception) {
            Log.e(TAG, "Error seeding database", ex)
            Result.failure()
        }
    }
}

Элемент DAO:

@Dao
interface ItemDao {

    @Query("SELECT * FROM items ORDER BY name")
    fun getItems(): LiveData<List<Item>>

    @Query("SELECT * FROM items WHERE itemId = :itemId")
    fun getItem(itemId: String): LiveData<Item>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertAll(items: List<Item>)

    @Query("SELECT * FROM items WHERE rowid IN (SELECT rowid FROM items_fts WHERE qualities MATCH :query) ORDER BY name")
    fun searchItems(query: String): LiveData<List<Item>>
}

Кроме того, если вам интересно, Я позаботился о том, чтобы изменить аннотацию% query на *.

^ (ПРИМЕЧАНИЕ). У меня нет такого опыта, и это может быть одной из причин, почему я изо всех сил пытаюсь придуматьрабочий раствор. Мне немного неясно, сколько работы Room будет выполнять за кулисами, и сколько мне нужно вмешиваться, когда дело доходит до генерации, заполнения, индексации и общего управления fts-аспектами. Ранее мое решение использовало поисковый запрос не-fts, который не требовал SQL, кроме самого запроса. Я не очень знаком с SQL, и я действительно не понимаю основы того, как работают миграции. Можно ли построить базу данных, а затем перенести ее в новую версию, не устанавливая сначала приложение, а затем мигрируя базу данных в обновленной версии? Если это не так и если для создания виртуальной таблицы fts требуется миграция, как вы можете отправить новое приложение для Android с готовым к использованию fts ?! Я чувствую, что в моих знаниях есть зияющие дыры, которые мешают мне прогрессировать. Будем весьма благодарны за любые хорошие предложения или предложенные решения!

...