Какой родной поисковик можно использовать для моего варианта использования? - PullRequest
1 голос
/ 24 июня 2019

Я работаю над приложением для Android, где некоторые защищенные данные будут храниться на устройстве Android и часто запрашиваться со стороны веб-приложения.Прямо сейчас я храню данные в SQLite БД.Когда приложение открывается, я загружаю полные данные из БД и подготавливаю карту фильтра для эффективных запросов памяти для веб-приложения.Однако для большого объема данных in-memory запрос может не быть масштабируемым решением.Мои поисковые запросы в основном полнотекстовый поиск.С чего мне начать?

Обновление 1

Как подсказывает Гаурав, я пытаюсь использовать виртуальную таблицу,

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 ИСПОЛЬЗУЯ FTS5 (заголовок, подзаголовок);] нет такого модуля: 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.

1 Ответ

1 голос
/ 24 июня 2019

Sqlite предоставляет возможность полнотекстового поиска. Я успешно использовал его для своего приложения, которое в реальном времени ищет 0,22 миллиона строк.

Вам необходимо создать виртуальную таблицу. И вставьте все свои данные в эту таблицу. Затем вам нужно обновить эту таблицу, когда появятся новые данные.

CREATE VIRTUAL TABLE table_name 
USING FTS4(column1,column2...);

ex -

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/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...