BCC32Cを使ってみた 本文へジャンプ

フリーウエア利用2    SQLite その3 全文検索・LIKE版

ホーム プログラミング メニュー 前へ 次へ
全文検索(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(データ項目)
 ・データ項目(条文)を検索して一致するレコードを表示する。
 

戻る 次へ