SQLiteを使ってAndroid端末内でお手軽に日本語全文検索する
タイトルの通り、SQLiteを使ってAndroid端末内でお手軽に日本語全文検索する方法です。
FTS
SQLiteにはFTSという全文検索用モジュールがサポートされているのでそれを使う。
最新版はFTS4で、Android APIレベル11以上なら標準で使えるようなのでFTS4を使う。
公式ドキュメント
SQLite FTS3 and FTS4 Extensions
N-gram
FTS標準のトークン作成処理はスペース区切りにしか対応していないので、日本語の場合、自分でトークンを作成する必要がある。トークン作成には、お手軽にトークンを作成できるN-gram方式を採用する。
以下が指定した値(N)でN-gram変換するだけのNgramクラス。
/** * N-gramクラス * @author shikato * */ public class Ngram { private Ngram() { } /** * N-gram変換したテキストを返す * @param aText N-gram変換するテキスト * @param aN N * @return N-gram変換されたテキスト */ public static String getNgramText( final String aText, final int aN ) { final StringBuilder ngramText = new StringBuilder(); final int length = aText.length(); if ( length < 1 ) { return ""; } if ( length > aN ) { int roop = length - aN; for ( int i = 0; i < roop; i++ ) { ngramText.append( aText.substring( i, i + aN ) ); ngramText.append( " " ); if ( i == ( roop - 1 ) ) { i++; ngramText.append( aText.substring( i, i + aN ) ); if ( i % aN >= aN ) { i++; ngramText.append( " " ); ngramText.append( aText.substring( i, i + aN ) ); } } } } else { ngramText.append( aText ); } return ngramText.toString(); } }
FTSテーブル作成
FTSテーブルでは値がすべて文字列扱いになってしまうので、実際に使用するときはメインのテーブルと全文検索用のFTSテーブルにわけて使うことが多くなると思う。
以下が上述したように、メインのテーブルと全文検索用のFTSテーブルにわけて作成する例。
CREATE TABLE hoge ( id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT ) CREATE VIRTUAL TABLE hoge_fts USING fts4( words TEXT )
検索対象テキストをメインテーブルのtextに格納し、検索対象テキストをN-gram変換したものを、FTSテーブルのwordsに格納する。
FTSテーブルを作成すると、docidというAUTO INCREMENTなカラムが自動的に用意されるので、メインテーブルと結合するときに使う。ちなみにdocidはrowidの別名なのでテーブル定義にはない。
あと、FTSでテーブルを作ると、~_contentのような名前のテーブル(Shadow Tables)が5つくらい勝手に作られるけど、普通に使う分にはあまり意識する必要はなさそう。
その辺りの詳細は公式ドキュメントに書いてある。
http://www.sqlite.org/fts3.html#section_9
保存
今回の例ではメインのテーブルとFTSテーブルにわけているので、両方のテーブルに保存する(メインのほうには通常のテキスト、FTSテーブルのほうにはN-gram変換したテキスト)。
※保存するテキストは、ユーザーの入力値になることがほとんどだと思うので、実際の開発時にはプリペアードステートメント等でSQLインジェクション対策する。
INSERT INTO hoge ( text ) VALUES( "hoge" ) INSERT INTO hoge_fts ( words ) VALUES( "ho og ge" )
同様に削除や更新の際も、両方のテーブルに対して実行する。
検索
MATCHを使用する。
SQLは以下のような感じになる。検索キーワードにN-gram変換したテキストを使用する。
※検索キーワードはユーザーの入力値になることがほとんどだと思うので、実際の開発時にはプリペアードステートメント等でSQLインジェクション対策する。
SELECT * FROM hoge h INNER JOIN hoge_fts hf ON h.id = hf.docid WHERE words MATCH "ho og ge"
前方一致だとこんな感じになる。
SELECT * FROM hoge h INNER JOIN hoge_fts hf ON h.id = hf.docid WHERE words MATCH "ho og ge*"
他にも色々な検索方法がある。
http://www.sqlite.org/fts3.html#section_3
パフォーマンス
SQLiteの.timerオプションを使用して測定。 投入したデータは5万件ほど。
普通にLIKE
SELECT count(*) from hoge WHERE text LIKE "%hoge%" CPU Time: user 0.104006 sys 0.240015
FTS メインテーブルとの結合なし
SELECT count(*) from hoge_fts WHERE words MATCH "ho og ge" CPU Time: user 0.000000 sys 0.000000
FTS メインテーブルとの結合あり
SELECT count(*) FROM hoge h INNER JOIN hoge_fts hf ON h.id = hf.docid WHERE words MATCH "ho og ge" CPU Time: user 0.004000 sys 0.000000
FTS 前方一致でメインテーブルとの結合あり
SELECT count(*) FROM hoge h INNER JOIN hoge_fts hf ON h.id = hf.docid WHERE words MATCH "ho og ge*" CPU Time: user 0.004001 sys 0.000000
やっぱりLIKEより速い。
まとめ
LIKEで検索するより速いし、別途ライブラリ等もいらないので、お手軽に端末内で日本語全文検索するときは使うと良いと思う。
Androidアプリ開発(Eclipse)で快適なGitHubライフを送る
最近のEclipseにはEgitという、Eclipse上でgitを使うためのプラグインが最初からインストールされているけど、これがとてつもなく使いづらかった。
ターミナル上でのgit操作に慣れていると、
git merge --no-ff hoge
ってEgitでどうやるんだっけ?みたいな感じで、コマンドだと直ぐ叩けるのにEgitだと調べないといけない、みたいな状況が煩わしかった。
なので、EclipseでGit(GitHub)使う時もコマンドで操作するようにした。
WindowsだとGit BASHが便利だった。
Git BASHは以下からダウンロードできる。
Git for Windows
最初の設定とか
SSH秘密鍵は以下に設置。
C:\Users\hoge\.ssh
ユーザ名とメールアドレスを設定。
git config --global user.name "hoge" git config --global user.email hoge@hoge.com
あとは、こんな感じで普通にgitコマンドが叩けるようになる。
Eclipseとの連携
よくある使用例としては、GitHubから
git clone hoge
して、Eclipseで
Import→Android→Existing Android Code Into Workspace
からcloneしてきたプロジェクトを取り込む。
リモートブランチに切り替える時は
git checkout -t origin/hoge
すればEclipse上でも切り替わる。たまに直ぐ反映されないときあるけど、Eclipse上でプロジェクトをリフレッシュすればOK。
mergeやpull、pushなども問題なく動く。プロジェクトに反映されないときは、checkout時と同じくリフレッシュすればOK。
その他設定とか
Git BASHは日本語の入力ができないっぽいので、commitコメント編集時に、日本語入力できるエディタを呼び出すように設定する。
git config --global core.editor "'hoge.exe'"
あとAndroidアプリ開発時の.gitignoreはこんな感じ。
*.apk *.ap_ *.dex .DS_Store *.class bin/ gen/ local.properties
Android Studioの場合は?
今更ながら、今日からAndroid Studio使ってみる予定。
とりあえずIdeaVIMっていう、Vrapperみたいな、vimっぽいキーバインドにするプラグインがあるみたいなので何とかなりそうな気がする(git関係ない)。
半年くらい仕事でAndroidアプリ開発していて役に立った本
せっかくはてなブログに移行したので、2年ぶりくらいだけど、お手軽まとめエントリーでも書く。
それでは以下が、半年くらい仕事でAndroidアプリ開発していて役に立った本達です。
- 作者: 中西葵,内村祐之,高橋良司
- 出版社/メーカー: シーアンドアール研究所
- 発売日: 2012/05/25
- メディア: 単行本(ソフトカバー)
- クリック: 6回
- この商品を含むブログ (1件) を見る
定番の逆引き本。1冊あると便利。
Android UI Cookbook for 4.0 ICS(Ice Cream Sandwich)アプリ開発術
- 作者: あんざいゆき
- 出版社/メーカー: インプレスジャパン
- 発売日: 2012/03/16
- メディア: 単行本(ソフトカバー)
- 購入: 2人 クリック: 47回
- この商品を含むブログ (18件) を見る
Androidデベロッパーにはお馴染みの、あんざいゆきさんの本。
Android4系のUIが主に紹介されてる。サンプルコード便利。
Master of Fragment (Android Professional Developerシリーズ) - 達人出版会
これも、あんざいゆきさんら著名なAndroidデベロッパー達が書いた本。
まだβ版らしいけど、Fragmentを使い出す前に読んでおけば良かったと思った本。
現場で使える〔逆引き+実践〕 Androidプログラミングテクニック
- 作者: 日本システム開発株式会社,石原正樹,松尾源,磯村禎孝,森靖晃,奥谷修治
- 出版社/メーカー: 技術評論社
- 発売日: 2012/07/19
- メディア: 単行本(ソフトカバー)
- 購入: 1人 クリック: 24回
- この商品を含むブログ (7件) を見る
Android版セカイカメラを作っていた会社の人達が書いた、逆引き系の書籍。
ちょっと古めだけど、デザインパターンや実践的なノウハウが載っているのが良かった。
Androidライブラリ実践活用[厳選111] (Software Design plus)
- 作者: 菊田剛
- 出版社/メーカー: 技術評論社
- 発売日: 2013/12/05
- メディア: 大型本
- この商品を含むブログ (3件) を見る
OSS紹介本達。有名そうなOSSが色々紹介されてる。便利OSS使っても良いし、コード読むと勉強になる。
立ち読みでも十分かもだけど、ひと通り知っておくと便利。
OSSアニメーションの挙動とか見るなら以下アプリが便利。
Libraries for developers - Google Play の Android アプリ
Android Pattern Cookbook マーケットで埋もれないための差別化戦略
- 作者: あんざいゆき
- 出版社/メーカー: インプレスジャパン
- 発売日: 2014/03/20
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
ABC 2014 Springであんざいゆきさんが紹介していた本。
その時のスライド。
最近流行のAndroidアプリのUIとかが紹介されてる。
エンジニアだけでなく「iPhoneと同じように作っといて」とか言うデザイナーも読めば良いと思う。
パーフェクトJava (PERFECT SERIES) (PERFECT SERIES 2)
- 作者: アリエル・ネットワーク株式会社,井上誠一郎,永井雅人,松山智大
- 出版社/メーカー: 技術評論社
- 発売日: 2009/09/24
- メディア: 大型本
- 購入: 26人 クリック: 360回
- この商品を含むブログ (35件) を見る
Java。どっちか読んでおくと良いと思う。
以下読んでないけど面白そう。
- 作者: Tae Yeon Kim,Hyung Joo Song,Ji Hoon Park,Bak Lee,Ki Young Lim,Androidフレームワーク研究会
- 出版社/メーカー: パーソナルメディア
- 発売日: 2013/12/18
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
オープンソース「Androidの教科書」プロジェクトのお知らせ | Tech Booster
以上です。