IT박스

Android의 전체 텍스트 검색 예

itboxs 2020. 9. 17. 07:25
반응형

Android의 전체 텍스트 검색 예


Android에서 전체 텍스트 검색 (FTS)을 사용하는 방법을 이해하는 데 어려움을 겪고 있습니다. FTS3 및 FTS4 확장에 대한 SQLite 설명서를 읽었습니다 . Android에서도 가능하다는 것을 알고 있습니다 . 그러나 이해할 수있는 예를 찾는 데 어려움을 겪고 있습니다.

기본 데이터베이스 모델

SQLite 데이터베이스 테이블 (이름 example_table)에는 4 개의 열이 있습니다. 그러나 text_column전체 텍스트 검색을 위해 인덱싱해야하는 열 (이름 )은 하나뿐입니다 . 의 모든 행 text_column에는 0에서 1000 단어까지 길이가 다양한 텍스트 포함됩니다. 총 행 수가 10,000보다 큽니다.

  • 테이블 및 / 또는 FTS 가상 테이블을 어떻게 설정 하시겠습니까?
  • FTS 쿼리를 text_column어떻게 수행 하시겠습니까?

추가 참고 사항 :

  • 하나의 열만 인덱싱해야하므로 FTS 테이블 만 사용하고 삭제하는 example_table것은 비 FTS 쿼리에 비효율적입니다 .
  • 이러한 큰 테이블의 text_column경우 FTS 테이블에 중복 항목을 저장하는 것은 바람직하지 않습니다. 이 게시물외부 콘텐츠 테이블 사용을 제안 합니다 .
  • 외부 콘텐츠 테이블은 FTS4를 사용하지만 FTS4는 Android API 11 이전에 지원되지 않습니다 . 대답은 API가 11 이상이라고 가정 할 수 있지만 더 낮은 버전을 지원하기위한 옵션에 대한 의견은 도움이 될 것입니다.
  • 원래 테이블의 데이터를 변경해도 FTS 테이블이 자동으로 업데이트되지 않으며 그 반대의 경우도 마찬가지입니다. 이 기본 예에서는 답변에 트리거포함 할 필요가 없지만 그럼에도 불구하고 도움이 될 것입니다.

가장 기본적인 답변

모든 것이 가능한 한 명확하고 읽을 수 있도록 아래의 일반 SQL을 사용하고 있습니다. 프로젝트에서 Android 편의 방법을 사용할 수 있습니다. db아래에 사용 객체는 SQLiteDatabase 의 인스턴스입니다 .

FTS 테이블 생성

db.execSQL("CREATE VIRTUAL TABLE fts_table USING fts3 ( col_1, col_2, text_column )");

이것은 onCreate()확장 SQLiteOpenHelper클래스 방법으로 갈 수 있습니다.

FTS 테이블 채우기

db.execSQL("INSERT INTO fts_table VALUES ('3', 'apple', 'Hello. How are you?')");
db.execSQL("INSERT INTO fts_table VALUES ('24', 'car', 'Fine. Thank you.')");
db.execSQL("INSERT INTO fts_table VALUES ('13', 'book', 'This is an example.')");

사용하는 것이 좋습니다 것 의 SQLiteDatabase # 삽입 또는 준비된 명령문 이상을 execSQL.

FTS 테이블 쿼리

String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_table WHERE fts_table MATCH ?", selectionArgs);

SQLiteDatabase # query 메서드를 사용할 수도 있습니다 . MATCH키워드에 유의하십시오 .

풀러 답변

위의 가상 FTS 테이블에 문제가 있습니다. 모든 열이 인덱싱되지만 일부 열을 인덱싱 할 필요가없는 경우 공간과 리소스가 낭비됩니다. FTS 인덱스가 필요한 유일한 열은 아마도 text_column.

이 문제를 해결하기 위해 일반 테이블과 가상 FTS 테이블의 조합을 사용합니다. FTS 테이블에는 인덱스가 포함되지만 일반 테이블의 실제 데이터는 포함되지 않습니다. 대신 일반 테이블의 내용에 대한 링크가 있습니다. 이를 외부 콘텐츠 테이블 이라고 합니다 .

여기에 이미지 설명 입력

테이블 만들기

db.execSQL("CREATE TABLE example_table (_id INTEGER PRIMARY KEY, col_1 INTEGER, col_2 TEXT, text_column TEXT)");
db.execSQL("CREATE VIRTUAL TABLE fts_example_table USING fts4 (content='example_table', text_column)");

Notice that we have to use FTS4 to do this rather than FTS3. FTS4 is not supported in Android before API version 11. You could either (1) only provide search functionality for API >= 11, or (2) use an FTS3 table (but this means the database will be larger because the full text column exists in both databases).

Populate the Tables

db.execSQL("INSERT INTO example_table (col_1, col_2, text_column) VALUES ('3', 'apple', 'Hello. How are you?')");
db.execSQL("INSERT INTO example_table (col_1, col_2, text_column) VALUES ('24', 'car', 'Fine. Thank you.')");
db.execSQL("INSERT INTO example_table (col_1, col_2, text_column) VALUES ('13', 'book', 'This is an example.')");

(Again, there are better ways in do inserts than with execSQL. I am just using it for its readability.)

If you tried to do an FTS query now on fts_example_table you would get no results. The reason is that changing one table does not automatically change the other table. You have to manually update the FTS table:

db.execSQL("INSERT INTO fts_example_table (docid, text_column) SELECT _id, text_column FROM example_table");

(The docid is like the rowid for a regular table.) You have to make sure to update the FTS table (so that it can update the index) every time you make a change (INSERT, DELETE, UPDATE) to the external content table. This can get cumbersome. If you are only making a prepopulated database, you can do

db.execSQL("INSERT INTO fts_example_table(fts_example_table) VALUES('rebuild')");

which will rebuild the whole table. This can be slow, though, so it is not something you want to do after every little change. You would do it after finishing all the inserts on the external content table. If you do need to keep the databases in sync automatically, you can use triggers. Go here and scroll down a little to find directions.

Query the Databases

String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_example_table WHERE fts_example_table MATCH ?", selectionArgs);

This is the same as before, except this time you only have access to text_column (and docid). What if you need to get data from other columns in the external content table? Since the docid of the FTS table matches the rowid (and in this case _id) of the external content table, you can use a join. (Thanks to this answer for help with that.)

String sql = "SELECT * FROM example_table WHERE _id IN " +
        "(SELECT docid FROM fts_example_table WHERE fts_example_table MATCH ?)";
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery(sql, selectionArgs);

Further Reading

Go through these documents carefully to see other ways of using FTS virtual tables:

Additional Notes


Don't forget when using content from to rebuild the fts table.

I do this with a trigger on update, insert, delete

참고URL : https://stackoverflow.com/questions/29815248/full-text-search-example-in-android

반응형