Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

SQLite3の全文検索機能"FTS"をつかってみる その4:論理条件

この手のもののご多分に漏れず、論理条件を突っ込むことが可能です。

実際のところ

eb2に含まれているサンプルは前回の記事と同様

OR

SELECT docid,body FROM eb2 WHERE body MATCH 'to OR have';
/*
1|All your base are belong to us.
36|The truck have started to move.
*/

AND

SELECT docid,body FROM eb2 WHERE body MATCH 'to AND have';
/*
36|The truck have started to move.
*/

NOT

あると地味に便利な否定論理も。

SELECT docid,body FROM eb2 WHERE body MATCH 'to NOT have';
/*
1|All your base are belong to us.
*/

SQLite3の全文検索機能"FTS"をつかってみる その3:NEAR節

SQLiteのFTSにおけるMATCHでは、NEARという構文があります。
コレを使うと、近くにこの言葉があるものだけマッチという、

実際のところ

たとえば、eb2(内容はその1とほぼ同様)にある"to"を含んだ文章を探すのは以下の通り。

SELECT docid,body FROM eb2 WHERE body MATCH 'to';
/*
1|All your base are belong to us.
36|The truck have started to move.
*/

ここで、
「前か後ろのどこにあるか忘れたけど近くにhaveがあるto」
とかいう妙ちくりんな条件で検索したくなったとします。
正規表現で出来なくも無いでしょうが、FTS4ならこんな風に書くことができます。

SELECT docid,body FROM eb2 WHERE body MATCH 'to NEAR have';
/*
36|The truck have started to move.
*/

SQLite3の全文検索機能"FTS"をつかってみる その2:既存のテーブルとの連携

FTS編その2、既存のテーブルをひも付けする方法です。

実際のところ

導入

まずは元になるtableを捏造。

CREATE TABLE t1(name, value);

INSERT INTO t1 VALUES("samplename", 123);
INSERT INTO t1 VALUES("shuzo", 456);
INSERT INTO t1 VALUES("taro", 789);

このtableを、FTS4対応の新造tableにひも付けします。

CREATE VIRTUAL TABLE t2 USING fts4(content="t1", name);

確認

フツーのtableは当然として

SELECT * FROM t1;
/*
samplename|123
shuzo|456
taro|789
*/

virtual tableの方も、参照先のtableに紐付いて入ってる事が確認できます。

SELECT * FROM t2;
/*
samplename
shuzo
taro
*/

SQLite3の全文検索機能"FTS"をつかってみる その1:導入

SQLite3には全文検索用の機能FTS3*1があります。
今回は導入と簡単な使い方。

下準備

全文検索対応カラムを作成します。
フツーのtableではなく、virtual tableていうものを使います。
既存のDBをコレに変換する方法については調査中……。

CREATE VIRTUAL TABLE ftssample1 USING fts3(content TEXT);

簡単に試したいので、仮データは3コほど……ゲーム由来の所謂EngRishから

INSERT INTO ftssample1 values('All your base are belong to us.');
INSERT INTO ftssample1 values('I feel asleep.');
INSERT INTO ftssample1 values('The truck have started to move.');

検索

使う分には楽で、基本的にはフツーのSELECTクエリです。

SELECT count(*) FROM ftssample1 WHERE content MATCH 'linux';
/* 0 */

SELECT count(*) FROM ftssample1 WHERE content MATCH 'to';
/* 2 */

SELECT count(*) FROM ftssample1 WHERE content MATCH 'a';
/* 0 */

ちょっと便利なワイルドカード検索

SELECT count(*) FROM ftssample1 WHERE content MATCH 'a*';
/* 2 */

MATCH節でカラムを指定する方法もあるみたいです。

SELECT * FROM ftssample1 WHERE ftssample1 MATCH 'content:all';
/* All your base are belong to us. 1 */

……と、これではタダのテキスト検索と何ら変わらないですね。
次回以降では

  • 既存tableのschemaをFTS対応化
  • AND/ORといった論理検索
  • 一致したフレーズの強調
  • インデックス付け

といった機能について扱っていきます。

*1:上位互換?にFTS4

pythonでsqlite3を扱う

sqliteSQL使いたいけど、DB鯖立てるほどで無いようなケースで重宝するRDBMSです。
RasPiで動かすような軽々システムでは大変重宝します。
pythonにはデフォでsqlite3用のライブラリが入っています。

実際のところ

利用開始

import sqlite3

DBの作成/読み込み

conn = sqlite3.connect('smaple.db')

テーブル作成

cur = conn.cursor()
cur.execute('CREATE TABEL people (name_last, age)')

書込

who = 'someone'
age = 99
cur.execute('INSERT INTO people VALUES (?,?)', (who, age))

読み込み

for row in conn.execute('SELECT * FROM people ORDER BY age'):
  print(row)

#> ('shuzo', 30)
#> ('someone', 99)

bottleでダウンロードリンクをつくる

今回の記事はbottleでダウンロードさせる方法についてです。
ローカルで生成した結果を読み込ませたり、webページに載せるにはちょっと分量が多くなりすぎる内容を掲載できますね。

実際のところ

imageディレクトリにgopherくんの画像"gopher.png"を用意しておきます。

スクリプト

最小限だとこんな感じ。
download用のライブラリは不要みたいです。

from bottle import run, static_file
from time import strftime

@get('/download/<filename:re:.*.png>')
def download(filename):
    return static_file(filename, root='/Users/shuzo_kino/python/image', download=filename)

run(host='localhost', port=8080)

bottleで静的な404ページ

bottleで静的な404ページを出す方法です

実際のところ

404ページのポンチ絵

htmlファイルとかでもいいのですが……デザインセンスなど一ビットもないのでポンチ絵で。
これを、imageフォルダにつっこみます。
f:id:shuzo_kino:20160906210349p:plain

スクリプト

最小限だとこんな感じ。

from bottle import run, static_file, error
from time import strftime

@error(404)
def error404(error):
    return static_file("404.png", root='/Users/shuzo_kino/python/image', mimetype='image/png')

run(host='localhost', port=8080)

動作確認

無効なアドレス……たとえば、http://localhost:8080/tなんかにアクセスすると先ほどの絵が出てきます