什么本机搜索引擎可用于我的用例?
What native search engine can be used for my use case?
我正在开发一个 android 应用程序,其中一些安全数据将存储在 android 设备中,并且经常从 Web 应用程序端查询。现在我将数据存储在 SQLite
数据库中。当应用程序打开时,我从数据库加载完整数据并准备一个过滤器映射,以便在内存中高效查询 Web 应用程序。但是,对于大量数据 in-memory
查询可能不是可扩展的解决方案。我的搜索查询基本上是全文搜索。我可以从哪里开始?
更新 1
按照 Gaurav 的建议,我正在尝试使用虚拟 table、
private const val SQL_CREATE_ENTRIES =
"CREATE VIRTUAL TABLE ${FeedReaderContract.FeedEntry.TABLE_NAME} USING FTS5 (" +
"${FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE}," +
"${FeedReaderContract.FeedEntry.COLUMN_NAME_SUBTITLE})"
创建 table、
时出错
[CREATE VIRTUAL TABLE entry USING FTS5 (title,subtitle);] no such module: FTS5
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.achellies.kotlin, PID: 30458
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.achellies.kotlin/com.achellies.kotlin.MainActivity}: android.database.sqlite.SQLiteException: no such module: FTS5 (code 1 SQLITE_ERROR[1])
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3086)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3229)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:6981)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
Caused by: android.database.sqlite.SQLiteException: no such module: FTS5 (code 1 SQLITE_ERROR[1])
at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method)
at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:946)
at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754)
at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:2228)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:2155)
at com.achellies.kotlin.FeedReaderDbHelper.onCreate(FeedReaderDbHelper.kt:19)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:393)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:298)
at com.achellies.kotlin.MainActivity.onCreate(MainActivity.kt:15)
at android.app.Activity.performCreate(Activity.java:7326)
at android.app.Activity.performCreate(Activity.java:7317)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3066)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3229)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:6981)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
更新 2
private const val SQL_CREATE_ENTRIES =
"CREATE VIRTUAL TABLE ${FeedReaderContract.FeedEntry.TABLE_NAME} USING FTS4 (" +
"${FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE}," +
"${FeedReaderContract.FeedEntry.COLUMN_NAME_SUBTITLE})"
这对我来说很好用。但是我不能 运行 使用经过清理的输入进行原始查询。
val query = "SELECT * FROM entry WHERE title MATCH '?'"
val args = arrayOf("Test")
val cursor: Cursor? = db.rawQuery(query, args)
运行时错误,
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.achellies.kotlin/com.achellies.kotlin.MainActivity}: java.lang.IllegalArgumentException: Cannot bind argument at index 1 because the index is out of range. The statement has 0 parameters.
Sqlite 提供全文搜索选项。我已经成功地将它用于我的应用程序,该应用程序在 real-time.
中搜索了 22 万个字符串
您需要创建一个虚拟 table。并在此 table.Then 中插入所有数据,当新数据出现时,您需要更新此 table。
CREATE VIRTUAL TABLE table_name
USING FTS4(column1,column2...);
例如 -
public boolean createFTS4Table() {
database = getWritableDatabase();
boolean success = true;
try {
database.execSQL("CREATE VIRTUAL TABLE if not exists fts_dict USING fts4 (id ,word)");
database.execSQL("INSERT INTO fts_dict SELECT rowid,word FROM entries");
} catch (Exception ex) {
ex.printStackTrace();
success = false;
Toast.makeText(ctx, "ERROR in FTS", Toast.LENGTH_SHORT).show();
}
return success;
}
要进行搜索,您可以使用 MATCH -
SELECT *
FROM posts
WHERE posts MATCH 'fts5';
Java -
getReadableDatabase().rawQuery("SELECT * FROM " + FTS_TABLE_NAME + " WHERE word match ?", new String[]{word + "*"}
更多 in-depth 文档 -
我正在开发一个 android 应用程序,其中一些安全数据将存储在 android 设备中,并且经常从 Web 应用程序端查询。现在我将数据存储在 SQLite
数据库中。当应用程序打开时,我从数据库加载完整数据并准备一个过滤器映射,以便在内存中高效查询 Web 应用程序。但是,对于大量数据 in-memory
查询可能不是可扩展的解决方案。我的搜索查询基本上是全文搜索。我可以从哪里开始?
更新 1
按照 Gaurav 的建议,我正在尝试使用虚拟 table、
private const val SQL_CREATE_ENTRIES =
"CREATE VIRTUAL TABLE ${FeedReaderContract.FeedEntry.TABLE_NAME} USING FTS5 (" +
"${FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE}," +
"${FeedReaderContract.FeedEntry.COLUMN_NAME_SUBTITLE})"
创建 table、
时出错[CREATE VIRTUAL TABLE entry USING FTS5 (title,subtitle);] no such module: FTS5
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.achellies.kotlin, PID: 30458
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.achellies.kotlin/com.achellies.kotlin.MainActivity}: android.database.sqlite.SQLiteException: no such module: FTS5 (code 1 SQLITE_ERROR[1])
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3086)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3229)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:6981)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
Caused by: android.database.sqlite.SQLiteException: no such module: FTS5 (code 1 SQLITE_ERROR[1])
at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method)
at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:946)
at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754)
at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:2228)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:2155)
at com.achellies.kotlin.FeedReaderDbHelper.onCreate(FeedReaderDbHelper.kt:19)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:393)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:298)
at com.achellies.kotlin.MainActivity.onCreate(MainActivity.kt:15)
at android.app.Activity.performCreate(Activity.java:7326)
at android.app.Activity.performCreate(Activity.java:7317)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3066)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3229)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:6981)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
更新 2
private const val SQL_CREATE_ENTRIES =
"CREATE VIRTUAL TABLE ${FeedReaderContract.FeedEntry.TABLE_NAME} USING FTS4 (" +
"${FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE}," +
"${FeedReaderContract.FeedEntry.COLUMN_NAME_SUBTITLE})"
这对我来说很好用。但是我不能 运行 使用经过清理的输入进行原始查询。
val query = "SELECT * FROM entry WHERE title MATCH '?'"
val args = arrayOf("Test")
val cursor: Cursor? = db.rawQuery(query, args)
运行时错误,
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.achellies.kotlin/com.achellies.kotlin.MainActivity}: java.lang.IllegalArgumentException: Cannot bind argument at index 1 because the index is out of range. The statement has 0 parameters.
Sqlite 提供全文搜索选项。我已经成功地将它用于我的应用程序,该应用程序在 real-time.
中搜索了 22 万个字符串您需要创建一个虚拟 table。并在此 table.Then 中插入所有数据,当新数据出现时,您需要更新此 table。
CREATE VIRTUAL TABLE table_name
USING FTS4(column1,column2...);
例如 -
public boolean createFTS4Table() {
database = getWritableDatabase();
boolean success = true;
try {
database.execSQL("CREATE VIRTUAL TABLE if not exists fts_dict USING fts4 (id ,word)");
database.execSQL("INSERT INTO fts_dict SELECT rowid,word FROM entries");
} catch (Exception ex) {
ex.printStackTrace();
success = false;
Toast.makeText(ctx, "ERROR in FTS", Toast.LENGTH_SHORT).show();
}
return success;
}
要进行搜索,您可以使用 MATCH -
SELECT *
FROM posts
WHERE posts MATCH 'fts5';
Java -
getReadableDatabase().rawQuery("SELECT * FROM " + FTS_TABLE_NAME + " WHERE word match ?", new String[]{word + "*"}
更多 in-depth 文档 -