【发布时间】:2023-03-19 12:36:01
【问题描述】:
我正在尝试在我的应用程序中实现 FTS4,该应用程序也使用 Room。根据我阅读的文档和教程,这不是一个非常复杂的设置,但我的查询触发了一个持久性错误,我似乎无法弄清楚。
正如我在 db 检查器中看到的那样,我的 fts 表正在正确创建和填充。此外,在我尝试使用 MATCH 运行任何查询之前,我可以对其运行查询并且没有问题。我得到以下内容
Error retrieving data from table.: unable to use function MATCH in the requested context (code 1 SQLITE_ERROR)
例如,这行得通(尽管使用起来没有意义):
SELECT * FROM community_features JOIN features_fts ON community_features.rowid = features_fts.rowid WHERE features_fts.feature_name LIKE '%TEST%'
但这不是:
SELECT * FROM community_features JOIN features_fts ON community_features.rowid = features_fts.rowid WHERE features_fts.feature_name MATCH '*TEST*'
更新 - 将我的应用与另一个应用进行比较,我注意到他们的 FTS 生成的文件比我的多。在我的数据库检查器中,我可以看到完整的 features_fts 表,但我没有看到其他应用程序中出现的 _docsize、_segdir、_segments 或 _stat 表。我猜这些应该以某种方式自动生成,这就是我的 MATCH 函数不起作用的原因。我是否错过了流程中的某个步骤?
以下是我的文件:
数据库设置
public class FeatureIndexDBClient {
private final FeatureIndexDB mDb;
private static String mDbName;
private static FeatureIndexDBClient mInstance;
private FeatureIndexDBClient(Context context, String dbName) {
if(mDbName == null || !mDbName.equalsIgnoreCase(dbName)) {
mDbName = dbName;
}
mDb = Room.databaseBuilder(context, FeatureIndexDB.class, dbName)
.addCallback(new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
db.execSQL("INSERT INTO features_fts(feature_name) VALUES ('rebuild')");
}
})
.fallbackToDestructiveMigration()
.build();
}
public static synchronized FeatureIndexDBClient getInstance(Context context, String dbName) {
if (mInstance == null || mDbName == null || !mDbName.equalsIgnoreCase(dbName)) {
mInstance = new FeatureIndexDBClient(context, dbName);
}
return mInstance;
}
public FeatureIndexDB getAppDatabase() {
return mDb;
}
public void close() {
this.mDb.close();
}
public SimpleSQLiteQuery getFeatureFTSQuery() {
return new SimpleSQLiteQuery("INSERT INTO features_fts(feature_name) SELECT community_features.feature_name FROM community_features");
}
}
实体:
@Entity(tableName = "community_features")
public class OSCommunityFeature implements Parcelable {
@NonNull
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "rowid")
private Long rowId;
@ColumnInfo(name = "_id")
private String _id;
@ColumnInfo(name = "community_id")
private int communityId;
@ColumnInfo(name = "feature_id")
private int featureId;
@ColumnInfo(name = "feature_type")
private Integer featureType;
@ColumnInfo(name = "feature_name")
private String feature_name;
public OSCommunityFeature() {
}
... constructors, getters, setters
}
@Entity(tableName = "features_fts")
@Fts4(contentEntity = OSCommunityFeature.class)
public class CommunityFeatureFTS {
@PrimaryKey
@ColumnInfo(name = "rowid")
private Long rowId;
@ColumnInfo(name = "feature_name")
private String feature_name;
public CommunityFeatureFTS() {
}
public CommunityFeatureFTS(Long id, String name) {
this.rowId = id;
this.feature_name = name;
}
在从服务器检索数据后填充该表。一旦数据加载到数据库中,我就会调用:
"INSERT INTO features_fts(feature_name) SELECT community_features.feature_name FROM community_features"
我的道如下:
@Dao
public interface FeatureIndexDAO {
// Community Features --------------------------------------------------------------------------
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAllFeatures(List<OSCommunityFeature> features);
@Transaction
@Query("SELECT * FROM community_features")
List<OSCommunityFeature> getAllFeatures();
@RawQuery
boolean setFeatureFTSTable(SupportSQLiteQuery query);
@Query("SELECT * FROM community_features JOIN features_fts ON community_features.rowid = features_fts.rowid WHERE features_fts.feature_name MATCH :searchFor")
List<OSCommunityFeature> searchForFeatures(String searchFor);
分级:
implementation "androidx.room:room-runtime:2.2.6"
annotationProcessor 'android.arch.persistence.room:compiler:2.2.6'
我一直在阅读我能找到的所有内容,但一直在使用 this tutorial 和 this。我可以从第一个链接下载示例项目,构建它并毫无问题地运行它。我真的说不出有什么不同。我已经来回走了大约一天了。
有人有任何提示或线索可以为我指明正确的方向吗?
【问题讨论】:
标签: android sqlite full-text-search android-room