フリーウエア利用2 SQLite その3 全文検索・LIKE版
SQLiteを使って全文検索(FTS、Full Text Search)を行うプログラムです。
ここでは、SQLのLIKE句を使った部分検索(例 %国民%)を行います。そのため、LIKE版(全文検索のような)としました。
・全文検索の例として日本国憲法を使います。学校の社会の授業で習うだれもが知っているもので、法律と同様に著作権がないことになっています。
・前文、条ごとに、章・条・連番をつなぎ合わせたインデックスを付加しています。
例

・データベース仕様、テーブル名、ファイル名(デフォルト)などのデータベースの定義や共通関数を「FTS_SQLITE.h」にまとめています。
・「FTS_LIKE.c」に、メニューからデータベースの作成(create_db)、インデックス・条文での検索( search_data)が選べます。
・SQLiteでは、「TEXT」項目のコードがUTF8ですので、S-JIS<->UTF8変換のため、NKF32を使用しています。
(コンパイル時にヘッダ、ライブラリが必要、実行時にはdllが必要)
全体を表示すると長くなるので「FTS_SQLITE.h」のDB定義部分と「FTS_LIKE.c」の検索部分を示します。ここで使用したソースコード、実行プログラム、DB、DBに読み込ませたテキストデータはこちらです。
@「FTS_SQLITE.h」、定義部分
// ===================================================================
// fts_sqlite.h SQLite・全文検索プログラム 共通関数・設定
// K.Nakamura 2023/09/03
// 1)FTS_LIKE 全文検索(LIKE版)
// @構造体定義 ASQLite 諸定義
// B関数(オープン・作成:open 、構造体にセット:set)
// ===================================================================
// ---------------- データ構造体定義 ------------------------------
// FTS_FILE データ
typedef struct
{
char *index_key; // 1 インデックス TEXT PK
char *fts_data; // 2 全文検索用データ TEXT
} FTS_LIKE_REC;
// FTS_LIKE_REC fts_like_rec;
// ------------ SQLite 全文検索 データベース定義 fts_like 用 --------
char *FTS_LIKE_tname = "FTS_LIKE";
char *FTS_LIKE_table = "index_key TEXT PRIMARY KEY , fts_data TEXT";
char FTS_LIKE_fname[500] = "fts_like.db";
char FTS_LIKE_ORG_fname[500] = "input.txt";
sqlite3 *fts_like_db;
sqlite3_stmt *fts_like_stmt_get ;
sqlite3_stmt *fts_like_stmt_insert ;
char *fts_like_sql_insert = "INSERT INTO FTS_LIKE values( ?1 , ?2 )";
A「FTS_LIKE.c」、検索関数
・メニュー部分です。
・読み込むデータは、1行目をヘッダー行とします。2行目以降はインデックス項目、データ文項目とし、TABで区切ります。
// =========================================================================
// Name : int main(void)
// Usage : メイン関数
// Parameter: なし
// Return :
// =========================================================================
int main( void )
{
int sel;
while(1){
fprintf(stdout, "□□□□□□□□□□□□□□□□□□□□□□□□□□\n");
fprintf(stdout, "□□ SQLite 全文検索(LIKE版)FTS_LIKE.exe □□\n");
fprintf(stdout, "□□□□□□□□□□□□□□□□□□□□□□□□□□\n");
fprintf(stdout, "\n");
fprintf(stdout, " 1 :データベース書き込み\n");
fprintf(stdout, " 2 :データベースファイル指定\n");
fprintf(stdout, " 3 :検索(インデックス)\n");
fprintf(stdout, " 4 :検索(文)\n");
fprintf(stdout, "\n");
fprintf(stdout, "選んでください(99:終了):");
scanf( "%d", &sel );
if(sel == 1) create_db(); //
else if (sel ==2) set_db(); //
else if (sel ==3) search_data( 1 );
else if (sel ==4) search_data( 2 );
else if (sel ==99 ) break;
}
fprintf(stdout, "\n");
return 0;
}
・検索部分です、インデックス部分の検索とデータ文部分の検索を同じ関数で処理します。
// =========================================================================
// Name : int search_data( int)
// Usage :SQLite・データベースを検索して、結果を表示する。
// Parameter: 1:インデックス,2:データ文
// Return : なし
// =========================================================================
int search_data( int id )
{
int rc;
char temp_s[300];
char temp_utf[900];
FTS_LIKE_REC ftsl;
int count;
char temp_statement[100];
// QA_DB_NEWのオープンまたは作成
rc = fts_like_open();
if(rc != 0) {
fprintf(stdout,"SQLite DB error%s\n", FTS_LIKE_fname);
return -1;
}
fprintf(stdout , "-------------------------------------------------\n");
if( id == 2) fprintf(stdout ,"検索する語(インデックス)を入力してください。:");
else fprintf(stdout ,"検索する語(文)を入力してください。:");
scanf( "%s", temp_s );
sprintf(sql_statement, "SELECT * FROM FTS_LIKE WHERE ");
SetNkfOption("-Swx");
NkfConvert( temp_utf, temp_s );
if( id == 2) sprintf(temp_statement, "fts_data like \'%%%s%%\' ",temp_utf);
else sprintf(temp_statement, "index_key like \'%%%s%%\' ",temp_utf);
strcat(sql_statement, temp_statement);
strcat(sql_statement, ";");
fprintf(stdout, "%s\n", sql_statement);
sqlite3_prepare_v2(fts_like_db, sql_statement , -1, &fts_like_stmt_get, NULL);
count=0;
fprintf(stdout , "-------------------------------------------------\n");
while(1){
// 1レコードごと読み込み
if(kbhit()!=0)break;
rc = sqlite3_step(fts_like_stmt_get);
if(rc != SQLITE_ROW){
fprintf(stdout, "--------------------\n");
fprintf(stdout, "検索終了(%d件)しました。\n",count);
break;
}
else{
count++;
fts_like_set(&ftsl);
fprintf(stdout, "--------------------\n");
fprintf(stdout, "%d 件目 [%s]\n",count ,ftsl.index_key );
fprintf(stdout, "【内容】:%s\n",ftsl.fts_data);
}
}
rc =sqlite3_reset(fts_like_stmt_get);
rc =sqlite3_finalize(fts_like_stmt_get);
fprintf(stdout , "-------------------------------------------------\n");
rc = sqlite3_close(fts_like_db);
return 0;
}
・コンパイル結果です。
・コンパイルには、sqlite、NKFのヘッダ(.h)とライブラリ(.lib)が必要です。取得方法は、
記載していますので、各自で取得をお願いしいます。
SQLiteはこちら、NKFはこちらのページを見てください。

C実行結果1(データベース作成)
・全文検索のSQLiteデータベースを元のデータを読み込んで作成します。
・各レコードはインデックス項目(プライマリー・キー、ユニークであること)、データ項目(条文が入る) ・このプログラムでは、読み込むファイル名と作成するるデータベースファイル名が指定できます。

D実行結果2(インデックス項目)
・インデックスを検索して一致するレコードを表示する。

E実行結果2(データ項目)
・データ項目(条文)を検索して一致するレコードを表示する。


|