Android Room - 未知标记器 - FtsOptions.TOKENIZER_UNICODE61

问题描述 投票:0回答:1

我使用 FTS4 和分词器来删除变音符号。数据库是用 Room 抽象出来的。

类似:

内容

@Entity(
        tableName = "test"
)
public class Test {

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    private Long mId;

    @ColumnInfo(name = "name")
    String mName;

    public Test(String name) {
        mName = name;
    }

    public Long getId() {
        return mId;
    }

    public void setId(Long id) {
        mId = id;
    }

    public String getName() {
        return mName;
    }

    public void setName(String name) {
        mName = name;
    }
}

FTS

@Entity(tableName = "search_fts")
@Fts4(
        contentEntity = Test.class,
        tokenizer = FtsOptions.TOKENIZER_UNICODE61,
        tokenizerArgs = {
                "remove_diacritics=2"
        }
)
public class SearchFts {

    @PrimaryKey
    @ColumnInfo(name = "rowid")
    int mRowId;

    @ColumnInfo(name = "name")
    String mName;

    public SearchFts(int rowId, String name) {
        mRowId = rowId;
        mName = name;
    }

    public int getRowId() {
        return mRowId;
    }

    public void setRowId(int rowId) {
        mRowId = rowId;
    }

    public String getName() {
        return mName;
    }

    public void setName(String name) {
        mName = name;
    }
}

这会产生 SQLite 查询:

CREATE VIRTUAL TABLE IF NOT EXISTS search_fts
USING FTS4(
     'name' TEXT,
     tokenize=unicode61 'remove_diacritics=2', content='test'
);

一切都适用于较新的 Android 版本(即 API 30),但在旧版本(即 API 25 或 27)上我收到以下错误:

android.database.sqlite.SQLiteException: unknown tokenizer (code 1)

官方文档:

“unicode61”标记生成器从 SQLite 版本 3.7.13 (2012-06-11) 开始可用。 Unicode61 的工作方式非常类似于“简单”,只不过它根据 Unicode 版本 6.1 中的规则进行简单的 unicode 大小写折叠,并且它识别 unicode 空格和标点字符并使用它们来分隔标记。

API和数据库版本:

日志猫:

2022-07-26 11:36:56.532 16176-16229/hr.laserline.osis E/SQLiteLog: (1) 语句在 28 处中止:[CREATE VIRTUAL TABLE IF NOT EXISTS

search_fts
USING FTS4(
name
TEXT, tokenize=unicode61
remove_diacritics=2
, content=
test
)] 未知分词器

.... 2022-07-26 11:36:56.539 16176-16229/hr.laserline.osis E/hr.laserline.osis.service.sync.SyncServicePresenter:同步错误!数据库事务回滚... android.database.sqlite.SQLiteException:未知分词器(代码1) 在 android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(本机方法) 在 android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:735) 在 android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754) 在 android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64) 在 android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1754) 在 android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1682) 在 androidx.sqlite.db.framework.FrameworkSQLiteDatabase.execSQL(FrameworkSQLiteDatabase.java:265) 在 hr.laserline.osis.data.db.LlamaRoomDatabase_Impl$1.createAllTables(LlamaRoomDatabase_Impl.java:148) 在 androidx.room.RoomOpenHelper.onCreate(RoomOpenHelper.java:74) 在 androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onCreate(FrameworkSQLiteOpenHelper.java:177) 在 android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:333) 在 android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:238) 在 androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:151) 在 androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:112) 在 androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:706) 在 androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:483) 在 hr.laserline.osis.data.db.dao.ParameterDao_Impl.getSyncNumPerChunk(ParameterDao_Impl.java:610) 在 hr.laserline.osis.data.repositories.ParameterRepository.getSyncNumPerChunk(ParameterRepository.java:72) 在 hr.laserline.osis.service.sync.SyncServiceInteractor.setNumPerChunk(SyncServiceInteractor.java:62) 在 hr.laserline.osis.service.sync.SyncServicePresenter.lambda$startSyncWithErp$0$hr-laserline-osis-service-sync-SyncServicePresenter(SyncServicePresenter.java:98) 在 hr.laserline.osis.service.sync.SyncServicePresenter$$ExternalSyntheticLambda2.get(来源未知:10) 在io.reactivex.rxjava3.internal.operators.observable.ObservableDefer.subscribeActual(ObservableDefer.java:33) 在 io.reactivex.rxjava3.core.Observable.subscribe(Observable.java:13176) 在 io.reactivex.rxjava3.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96) 在io.reactivex.rxjava3.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:38) 在io.reactivex.rxjava3.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:25) 在 java.util.concurrent.FutureTask.run(FutureTask.java:266) 在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 在 java.lang.Thread.run(Thread.java:764) 在 hr.laserline.osis.utils.SingleTaskExecutor$1.run(SingleTaskExecutor.java:118)

有什么建议吗?

android sqlite android-sqlite android-room fts4
1个回答
0
投票

这不仅仅是 Room,这是 FTS3-4/unicode61 tokenizer 的普遍问题。

简单来说

  • tokenize=unicode61
    有 Android
    minSdk = 21
    要求。
  • tokenize=unicode61 'remove_diacritics=0|1'
    有 Android
    minSdk = 21
    要求。
  • tokenize=unicode61 'remove_diacritics=2'
    有 Android
    minSdk = 30
    要求。

SQLite 3.27.0(从 Android API 30 开始嵌入)有这一行:

向 FTS3 和 FTS5 添加了 remove_diacritics=2 选项。

请参阅我的博客了解完整详细信息。

© www.soinside.com 2019 - 2024. All rights reserved.