【问题标题】:What native search engine can be used for my use case?我的用例可以使用什么本地搜索引擎?
【发布时间】:2019-11-05 21:12:06
【问题描述】:

我正在开发一个 android 应用程序,其中一些安全数据将存储在 android 设备中,并经常从 web 应用程序端查询。现在我将数据存储在SQLite DB 中。当应用程序打开时,我正在从 DB 加载完整数据并准备过滤器映射以有效地为 Web 应用程序进行内存查询。但是,对于大量数据in-memory 查询可能不是可扩展的解决方案。我的搜索查询基本上是全文搜索。我可以从哪里开始?

更新 1

按照 Gaurav 的建议,我正在尝试使用虚拟表,

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})"

创建表时出错,

[CREATE VIRTUAL TABLE entry USING FTS5 (title,subtitle);] 没有这样的模块: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.

【问题讨论】:

  • 17k 代表和 8 年在这个网站上,你现在应该知道,要求图书馆推荐是题外话,会解决你的问题
  • @TimCastelijns 这篇文章已经遇到了一个特定的问题。现在,我正在与一个有良好意愿提供帮助的人讨论具体问题。要求您恢复您的近距离投票。
  • 只要您的问题是“如果我的应用程序中有众所周知的数据查询框架或库可以在数据库上运行查询,我想申请”,您与他讨论什么都没关系或者他的意图是什么。也许更新你的问题会更好
  • @TimCastelijns 我更新了帖子。请求恢复投票以供您考虑。

标签: android search kotlin native search-engine


【解决方案1】:

Sqlite 提供全文搜索选项。我已经成功地将它用于我的应用程序,该应用程序可以实时搜索 22 万个字符串。

您需要创建一个虚拟表。并将你所有的数据插入到这个表中。然后当有新数据出现时你需要更新这个表。

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 + "*"}

如需更深入的文档 -

http://www.sqlitetutorial.net/sqlite-full-text-search/

【讨论】:

  • Gaurav,我收到错误 no such module: FTS5 (code 1 SQLITE_ERROR[1])。您的意思是 Android 默认 SQLite fw 支持虚拟表还是我需要 gradle 支持?
  • 我认为 android 支持 FTS4(我使用的那个)。我已经更改了帖子中的语法。
  • Gaurav,您确定您的示例查询字符串正确吗? SELECT * FROM posts WHERE posts MATCH 'fts5'; posts 是表名,第二个帖子是什么?这让人困惑。
  • 我可以看到您使用 FTS5 创建表,请使用 fts4。 (参见 java 示例)。此外,我还添加了用于搜索的 java 代码。 (我不知道 kotlin 对不起!)
  • 高拉夫,感谢您的支持。但是,使用 FTS4 rawQuery 时我无法绑定输入。你能帮我更新帖子吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-31
  • 2011-12-08
  • 1970-01-01
  • 1970-01-01
  • 2012-10-09
  • 1970-01-01
相关资源
最近更新 更多