Node.jsとSQLiteで全文検索・一歩前
データベースに文字列を保存して、全文検索できるようにしたい。 でも、マネーレスでクラウドのデータベースサービスは使いたくない。 そんな悩みに答えるかもしれないSQLite。 今ではAWSのLambdaにdbファイルをデプロイして、使う人も出てきている。
AWSのLambda + sqlite でサーバレスRDSもなしでAPI実装
実サービスでAWS Lambda内でsqlite3を使った話
このようにお手軽なSQLiteだが、実は全文検索も行うことができる。 SQLiteで全文検索しようとすると、fts(Full Text Search)という拡張機能を有効にしてコンパイルする必要があるが、npmならこのコンパイルも簡単にできる。
fts機能を有効にしたSQLiteのインストール
export CFLAGS="-DSQLITE_ENABLE_FTS3_PARENTHESIS" npm install sqlite3 --build-from-source
node-sqlite3の導入
npm install https://github.com/mapbox/node-sqlite3/tarball/master
テーブルの作成
このライブラリを使えば、とても簡単にデータベースを操作できる。
例えば、テーブルを作成するコードは以下のようになる。
a,b,cという3つのカラムを持つテーブルを作成する関数である。
クエリ文のVIRTUAL
というのは、仮想テーブルを作成するためのもの。
SQLiteで全文検索するためには、普通のテーブルではなく、専用の仮想テーブルを作成する必要がある。
import sqlite3 from "sqlite3" const createTable = (tableName) => { const db = new sqlite3.Database('test.db') db.serialize(() => { let queryString = "CREATE VIRTUAL TABLE " + tableName + " USING fts4('a', 'b', 'c')" db.run(queryString) db.close() }) } createTable("test")
テーブルにデータを挿入
const insertData = (tableName) => { const db = new sqlite3.Database('test.db') db.serialize(() => { let prepare = db.prepare("INSERT INTO " + tableName + " VALUES (?, ?, ?)") const insertDataList = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] insertDataList.forEach((value, index, array) => { prepare.run(value, (err) => { if(err){ throw err } }) }) }) db.close(); } insertData("test")
テーブルのデータを見る
const showTableData = (tableName) => { const db = new sqlite3.Database('test.db') db.serialize(() => { db.each("select * from " + tableName, (err, row) => { console.log(row) }) }) db.close(); } showTableData("test") /* { a: 1, b: 2, c: 3 } { a: 4, b: 5, c: 6 } { a: 7, b: 8, c: 9 } */
全文検索機能が有効になったことを確認
本題の全文検索であるが、MATCH句を使用して行う。 以下の検索は、検索対象が行に存在すれば、行全体を返してくれる。 今回はMATCH句が使えるようになり、全文検索機能が有効になるところまでを確認しておく。
const searchFullText = (tableName, searchWord) => { const db = new sqlite3.Database('test.db') db.serialize(() => { let queryString = "SELECT * FROM " + tableName + " WHERE " + tableName + " MATCH " + "'" + word + "'" db.each(queryString, (err, row) => { if (err) { throw err } console.log(row) }) }) db.close(); } searchFullText("test", 1) //{ a: 1, b: 2, c: 3 } searchFullText("test", 4) //{ a: 4, b: 5, c: 6 } searchFullText("test", 7) //{ a: 7, b: 8, c: 9 }
まとめ
ここから日本語の全文検索ができるようにするには、検索アルゴリズムをきちんと考えてやらねばならない。 関連キーワードは、部分一致、前方一致、N-Gram、分かち書き、Mecabなど。 マネーで何事も解決できる人は、こんなことやらずともAWSのElasticSearchやAlgoliaを使えばよろし。