가장 기본적인 답변
모든 것이 가능한 한 명확하고 읽기 쉽게 아래의 일반 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)");
이를 위해 FTS3 대신 FTS4를 사용해야합니다. FTS4는 API 버전 11 이전의 Android에서 지원되지 않습니다. (1) API> = 11에 대한 검색 기능 만 제공하거나 (2) FTS3 테이블을 사용할 수 있습니다 (그러나 이는 전체 텍스트 열이 존재하기 때문에 데이터베이스가 더 커진다는 것을 의미합니다). 두 데이터베이스 모두).
테이블 채우기
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.')");
(다시 말하지만,를 execSQL
사용하는 것보다 do inserts에 더 나은 방법이 있습니다 . 저는 가독성을 위해 사용하고 있습니다.)
지금 FTS 쿼리를 시도하면 fts_example_table
결과가 나타나지 않습니다. 그 이유는 한 테이블을 변경해도 다른 테이블이 자동으로 변경되지 않기 때문입니다. FTS 테이블을 수동으로 업데이트해야합니다.
db.execSQL("INSERT INTO fts_example_table (docid, text_column) SELECT _id, text_column FROM example_table");
( 일반 테이블 의 docid
경우와 같습니다 rowid
.) 외부 콘텐츠 테이블을 변경할 때 (INSERT, DELETE, UPDATE) 할 때마다 FTS 테이블을 업데이트 (인덱스를 업데이트 할 수 있도록)해야합니다. 이것은 번거로울 수 있습니다. 미리 채워진 데이터베이스 만 만드는 경우 다음을 수행 할 수 있습니다.
db.execSQL("INSERT INTO fts_example_table(fts_example_table) VALUES('rebuild')");
전체 테이블을 다시 빌드합니다. 그러나 이것은 느릴 수 있으므로 약간의 변화가있을 때마다하고 싶은 일이 아닙니다. 외부 컨텐츠 테이블에 대한 모든 삽입을 완료 한 후에 수행합니다. 데이터베이스를 자동으로 동기화해야하는 경우 트리거 를 사용할 수 있습니다 . 여기 로 이동하여 약간 아래로 스크롤하여 방향을 찾으십시오.
데이터베이스 쿼리
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_example_table WHERE fts_example_table MATCH ?", selectionArgs);
이번에는 text_column
(및 docid
) 에만 액세스 할 수 있다는 점을 제외하면 이전과 동일합니다 . 외부 콘텐츠 테이블의 다른 열에서 데이터를 가져와야하는 경우 어떻게해야합니까? 때문에 docid
FTS의 테이블이 일치합니다 rowid
(이 경우 _id
외부 콘텐츠 테이블의)을, 당신은 가입 할 수 있습니다. ( 이 답변 에 감사드립니다 .)
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);
추가 읽기
FTS 가상 테이블을 사용하는 다른 방법을 보려면 다음 문서를주의 깊게 살펴보십시오.
추가 참고 사항