SQLiteで全文検索

検索機能付きのAndroidアプリを作るために、ドキュメントを読んでいるとCreating a Search Interface  |  Android Developersという項目があり、SQLite全文検索モジュール:SQLite FTS3 and FTS4 Extensionsがあることを知った。

Androidアプリに組み込む前に、FTS3を使ってみた。

$ sqlite3 database.sqlite
SQLite version 3.7.6
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> CREATE VIRTUAL TABLE AddressBook USING fts3(name TEXT, address TEXT);

-- FTS3を使う表はVIRTUAL TABLEにする必要がある

sqlite> INSERT INTO AddressBook VALUES("Alice", "Albany, Crossgates");
sqlite> INSERT INTO AddressBook VALUES("Bob", "Buffalo, Walden Galleria");
sqlite> INSERT INTO AddressBook VALUES("Carol", "Garden City, Roosevelt Field");
sqlite> INSERT INTO AddressBook VALUES("Dave", "Huntington Station, Walt Whitman");
sqlite> INSERT INTO AddressBook VALUES("Eve", "Lake Grove, Smith Haven");
sqlite> INSERT INTO AddressBook VALUES("Mallory", "Manhasset, Manhasset");
sqlite> INSERT INTO AddressBook VALUES("Peggy", "New York City, Fifth Avenue");
sqlite> INSERT INTO AddressBook VALUES("Victor", "New York City, SoHo");
sqlite> INSERT INTO AddressBook VALUES("Trent", "New York City, Upper West Side");
sqlite> INSERT INTO AddressBook VALUES("Walter", "New York City, West 14th Street");
sqlite> INSERT INTO AddressBook VALUES("Arthur", "Staten Island, Staten Island");
sqlite> INSERT INTO AddressBook VALUES("Merlin", "Syracuse, Carousel");
sqlite> INSERT INTO AddressBook VALUES("Paul", "Victor, Eastview");
sqlite> INSERT INTO AddressBook VALUES("Carole", "West Nyack, Palisades");
sqlite> INSERT INTO AddressBook VALUES("Chuck", "White Plains, The Westchester");

sqlite> .tables
AddressBook           AddressBook_segdir  
AddressBook_content   AddressBook_segments

表の指定桁に対して全文検索をするには、MATCH queryを使う。

sqlite> SELECT docid, * FROM AddressBook WHERE address MATCH 'City';
3|Carol|Garden City, Roosevelt Field
7|Peggy|New York City, Fifth Avenue
8|Victor|New York City, SoHo
9|Trent|New York City, Upper West Side
10|Walter|New York City, West 14th Street

-- LIKEを使っても同じ結果が得られるが、MATCHを使った方が速い。

sqlite> SELECT docid , * FROM AddressBook WHERE address LIKE '%City%';
3|Carol|Garden City, Roosevelt Field
7|Peggy|New York City, Fifth Avenue
8|Victor|New York City, SoHo
9|Trent|New York City, Upper West Side
10|Walter|New York City, West 14th Street

Google検索をするように、AND/OR/NOT検索、PHRASE検索が出来る。

-- AND
sqlite> SELECT * FROM AddressBook WHERE address MATCH 'West City';
Trent|New York City, Upper West Side
Walter|New York City, West 14th Street

-- OR
sqlite> SELECT * FROM AddressBook WHERE address MATCH 'West OR City';
Carol|Garden City, Roosevelt Field
Peggy|New York City, Fifth Avenue
Victor|New York City, SoHo
Trent|New York City, Upper West Side
Walter|New York City, West 14th Street
Carole|West Nyack, Palisades

-- NOT
sqlite> SELECT * FROM AddressBook WHERE address MATCH 'New -West';
Peggy|New York City, Fifth Avenue
Victor|New York City, SoHo

-- PHRASE
sqlite> SELECT * FROM AddressBook WHERE address MATCH '"New City"';

また、ワイルドカードマッチングも出来る。

sqlite> SELECT * FROM AddressBook WHERE address MATCH 'West S*';
Trent|New York City, Upper West Side
Walter|New York City, West 14th Street

sqlite> SELECT * FROM AddressBook WHERE address MATCH '"N* Y*"';
Peggy|New York City, Fifth Avenue
Victor|New York City, SoHo
Trent|New York City, Upper West Side
Walter|New York City, West 14th Street

AとBの単語を指定し、その単語間の距離を指定して検索することも出来る。

sqlite> SELECT * FROM AddressBook WHERE address MATCH 'New NEAR West';
Trent|New York City, Upper West Side
Walter|New York City, West 14th Street

-- default: NEAR/10

sqlite> SELECT * FROM AddressBook WHERE address MATCH 'New NEAR/2 West';
Walter|New York City, West 14th Street


マッチした単語を強調表示するために、snippet functionがある。

sqlite> SELECT snippet(AddressBook) FROM AddressBook WHERE address MATCH 'City';
Garden <b>City</b>, Roosevelt Field
New York <b>City</b>, Fifth Avenue
New York <b>City</b>, SoHo
New York <b>City</b>, Upper West Side
New York <b>City</b>, West 14th Street

-- default: <b> and </b>

sqlite> SELECT snippet(AddressBook, "[", "]") FROM AddressBook WHERE address MATCH 'York';
New [York] City, Fifth Avenue
New [York] City, SoHo
New [York] City, Upper West Side
New [York] City, West 14th Street