掲示板に検索機能をつける:4. 掲示板データーを検索用インデックスに登録する

前回(d:id:paz3:20090719:1247984217)、フィルタを作成したので、今回はそのフィルタを使って掲示板データーを登録します。

検索用インデックスと掲示板データーの場所を決める

検索用インデックス(データベース)と掲示板データーの場所は次のようにします。

/home/myname/www/
  test/
    data/
      search/
        db       … 検索用インデックス
  bbs/
    dat/
      *.dat      … 掲示板データー

検索用インデックスを作成する

以下の手順で検索用インデックスを作成しました。以下ではすべてbashで操作しています。

$ cd /home/myname/www/test/data/search
$ estcmd create -attr @title str -attr @mdate seq -attr @size seq db

http://hyperestraier.sourceforge.net/uguide-ja.html」の「お洒落な入力フォーム」を参考に、“-attr”オプションで以下の属性インデックスを作成しています。

属性名 属性の意味 データ型
@title スレッドタイトル 文字列型
@mdate スレッドの最終更新日 シーケンシャル型
@size スレッドのサイズ シーケンシャル型

データー格納用のスクリプトを作成する

検索用インデックスにデーターを格納するには、estcmd gatherを使います。estcmd gatherにはたくさんのオプションを指定する必要があるため、ここではファイル名またはディレクトリ名を与えると、それにオプションを付けてestcmd gatherに引き渡すスクリプト“make_search_index_of_file”を作成しました。

make_search_index_of_file:

#!/usr/bin/env bash
# 指定されたファイルまたはディレクトリの検索用インデックスを作成する。

PATH=/usr/bin:/usr/local/bin:/home/myname/bin
DB_PATH=/home/myname/www/test/data/search/db
OPTIONS="-cl -fx .dat H@estfxbbstohtml -fz -il ja -ic UTF-8 -sd -cm"

if [ $# != 1 ]; then
  echo "Usage: $0 {file|dir}"
  exit 0
fi
estcmd gather $OPTIONS $DB_PATH $1

このスクリプトではestcmd gatherに以下のようなオプションを指定しています。

オプション表現 意味
-cl 上書きされた文書の領域を整理します
-fx .dat H@estfxbbstohtml ファイル名が*.datに対してフィルターを指定しています
-fz ファイル名が*.datではないファイルを無視します
-il ja 文字コードの判定で日本語を優先します
-ic UTF-8 掲示板データーの文字コードUTF-8に指定しています
-sd ファイルの更新日時を文書の属性として追加します
-cm 文書の属性の更新日時がファイルの更新日時より古い場合のみ登録します

オプション-fxの“H@estfxbbstohtml”というのは、「estfxbbstohtmlをフィルタとして使い、その出力をHTMLとみなして登録する」という意味です。

データー・ファイルの数を調べる

上記のmake_search_index_of_fileにデーターのあるディレクトリを指定すると、すべてのデーターを一気に登録することができます。しかし、レンタルサーバー上でCPUを長時間占有するのは良くないと考え、細かく分割して登録することにします。

まずはデーター・ファイルのファイル名と数を調べます。

$ cd /home/myname/www/bbs/dat
$ ls *.dat | head -3
1219509528.dat
1219511655.dat
1219511701.dat
$ ls *.dat | tail -3
1248431383.dat
1248431750.dat
1248431841.dat
$ ls *.dat | wc -l
    5066

データーは“1219509528.dat”〜“1248431841.dat”の5066ファイルありました。このファイル名は、スレッドが作成された日時のUNIX Time(1970年1月1日からの累積秒)の値になっています。条件を変えながら次のようなコマンドで調べたところ、先頭4桁が同じファイルごとに登録すれば、1回350ファイル以下×30回ですべてのファイルが登録できることがわかりました。

$ cd /home/myname/www/bbs/dat
$ ls -1 *.dat | sed 's/^\(....\).*$/\1/' | sort | uniq -c
  60 1219
 149 1220
 288 1221
(中略)
 126 1246
 103 1247
   4 1248
$ ls -1 *.dat | sed 's/^\(....\).*$/\1/' | sort | uniq | wc -l
      30

各行の後ろの数値がファイル名の先頭部分、前の数値がファイルの数です。

データーを分割して登録するスクリプトを作成する

以上をふまえ、ファイル名の先頭4桁ごとに分割してデーター登録をするスクリプト“make_initial_search_index”を作成しました。

make_initial_search_index:

#!/usr/bin/env bash
# 掲示板データーを検索用インデックスに一括初期登録する。

PATH=/usr/bin:/usr/local/bin:/home/myname/bin
SOURCE_DIR=/home/myname/www/bbs/dat

function main {
  I=1219
  while [ $I -le 1248 ]; do
    echo -- Make index of file $I\*.dat ---
    echo Hit return key.
    pause
    make_index $I
    let I=I+1
  done
}

function pause {
  local DUMMY
  read DUMMY
}

function make_index {
  find $SOURCE_DIR -name $1\*.dat -print | make_search_index_of_file -
}

main

estcmd gatherはファイル名として“-”を渡すと、標準入力からファイル名を読み込んで登録します。estcmd gatherを使用しているmake_search_index_of_fileも同様の動作をします。ここではmake_search_index_of_fileの引数に“-”を指定し、findを使って標準入力にファイル名を渡しています。

データーを登録する

上記のスクリプトmake_initial_search_indexを実行すると、まず次のようにファイル名を表示して一時停止します。

$ make_initial_search_index
-- Make index of file 1219*.dat ---
Hit return key.

Enterを入力すると、データーを登録します。登録が終わると次のファイル名を表示して一時停止します。

estcmd: INFO: reading list from the standard input
estcmd: INFO: status: name=/home/myname/www/test/data/search/db dnum=60 wnum=28615 fsiz=12176079 crnum=0 csiz=0 dknum=0
estcmd: INFO: 1 (/home/myname/www/bbs/dat/1219509528.dat): registered
estcmd: INFO: 2 (/home/myname/www/bbs/dat/1219511655.dat): registered
estcmd: INFO: 3 (/home/myname/www/bbs/dat/1219511701.dat): registered
(中略)
estcmd: INFO: 58 (/home/myname/www/bbs/dat/1219987413.dat): registered
estcmd: INFO: 59 (/home/myname/www/bbs/dat/1219988385.dat): registered
estcmd: INFO: 60 (/home/myname/www/bbs/dat/1219990768.dat): registered
estcmd: INFO: flushing index words: name=/home/myname/www/test/data/search/db dnum=209 wnum=28616 fsiz=12504514 crnum=27000 csiz=1674216 dknum=0
estcmd: INFO: flushing index words: name=/home/myname/www/test/data/search/db dnum=209 wnum=33713 fsiz=12822111 crnum=17000 csiz=1018580 dknum=0
estcmd: INFO: flushing index words: name=/home/myname/www/test/data/search/db dnum=209 wnum=39138 fsiz=13074620 crnum=7000 csiz=446981 dknum=0
estcmd: INFO: closing: name=/home/myname/www/test/data/search/db dnum=209 wnum=43446 fsiz=13362323 crnum=0 csiz=0 dknum=0
estcmd: INFO: finished successfully: elapsed time: 0h 0m 6s
-- Make index of file 1220*.dat ---
Hit return key.

なるべくサーバーの負荷が低くなるように、適当な間隔をあけながらEnterキーを押すことを繰り返しました。
これで掲示板データーを検索用インデックスに登録することができました。