検索結果をアクセスランキング順にソートする方法(1) ― 2006年03月23日 10時44分46秒
Namazu には、検索結果をアクセスランキング順にソートして表示する機能はありません。 しかし、補助プログラムとフィールドソート機能を組み合わせることで、(いくらかの制限事項はあるものの)それを実現することは可能です。
NMZ.field.accessrank というフィールドに各文書のアクセス数を記録してあるならば、CGI パラメータの sort に field:accessrank:descending を設定すると、アクセス数の多い順に結果を表示することができます。
NMZ.head.ja のソート部分を以下のように修正します。
<option selected value="field:accessrank:descending">
アクセスランキング (高)
<option value="field:accessrank:ascending">
アクセスランキング (低)
<!--
<option selected value="score">スコア
-->
また、NMZ.result.normal.ja を以下のように修正します。
<dt>${namazu::counter}. <strong>
<a href="/cgi-bin/link.cgi?uri=${uri}">${title}
</a></strong>
(アクセス数: ${accessrank})</dt>
<dd><strong>著者</strong>: <em>${author}</em></dd>
<dd><strong>日付</strong>: <em>${date}</em></dd>
<dd>${summary}</dd>
<dd><a href="/cgi-bin/link.cgi?uri=${uri}">
${uri}</a> (${size} bytes)<br><br></dd>
検索結果をアクセスランキング順にソートする方法(2) ― 2006年03月23日 10時59分31秒
NMZ.field.accessrank に各文書のアクセス数があれば、アクセスランキング順にソートできることを(1)で示しました。
(2)では、NMZ.field.accessrank を作成する方法をしめします。
キーとして NMZ.field.uri を、値はアクセス数でSDBMで管理することにします。
SDBM から NMZ.field.accessrank を生成するには、次に示すdbupdate.pl を使います。
dbupdate.pl はインデックスのあるディレクトリで実行します。
#!/usr/bin/perl
use Fcntl;
use SDBM_File;
use Config;
my $flags = O_CREAT | O_RDWR | BINARY();
tie( %dbhash, 'SDBM_File', 'NMZ.sdbm.accessrank', $flags, 0666)
or die "Cannot open database $!";
chmod 0666, 'NMZ.sdbm.accessrank.dir', 'NMZ.sdbm.accessrank.pag';
my $nmz_uri = "NMZ.field.uri";
my $nmz_access_rank = "NMZ.field.accessrank";
open(NMZ_URI, "< $nmz_uri") || die "Cannot open file $!";
binmode NMZ_URI;
open(NMZ_ACCESS_RANK, "> $nmz_access_rank.$$.tmp")
or die "Cannot open file $!";
binmode NMZ_ACCESS_RANK;
open(NMZ_ACCESS_RANK_I, "> $nmz_access_rank.i.$$.tmp")
or die "Cannot open file $!";
binmode NMZ_ACCESS_RANK_I;
chmod 0666, "$nmz_access_rank.$$.tmp", "$nmz_access_rank.i.$$.tmp";
my $offset = 0;
while(my $uri = <NMZ_URI>) {
my $count;
chomp $uri;
if (exists($dbhash{$uri})) {
$count = $dbhash{$uri};
} else {
$count = 0;
}
printf NMZ_ACCESS_RANK "%-10d\n", $count;
print NMZ_ACCESS_RANK_I pack('N', $offset);
$offset += 11;
}
close(NMZ_ACCESS_RANK_I);
close(NMZ_ACCESS_RANK);
rename("$nmz_access_rank.$$.tmp", "$nmz_access_rank");
rename("$nmz_access_rank.i.$$.tmp", "$nmz_access_rank.i");
close(NMZ_URI);
untie( %dbhash );
sub BINARY {
return O_BINARY if $Config{osname} =~ /^(MS)?Win/;
}
検索結果をアクセスランキング順にソートする方法(3) ― 2006年03月23日 11時22分44秒
(3)では、リンクをクリックした時に、アクセス数をカウントする部分を紹介します。
次の link.cgi を /cgi-bin/ に置きます。
- 1行目のPerl のパスは各環境に合わせて書き換えます。
- link.cgi には chmod +x で実行属性を付けます。
- $index にはインデックスのパスを指定します。
- Replace 部分は、.namazurc で設定した逆のものを設定します。(逆変換)
- インデックスのあるディレクトリは、CGI の実行ユーザに対して書き込み許可が必要です。
#!/usr/bin/perl
use CGI;
use Fcntl;
use SDBM_File;
use Config;
sub safe_die($);
my $index = "/usr/local/var/namazu/index";
my $query = new CGI;
my $uri = $query->param('uri');
my $path = $uri;
# Replace
$path =~ s!^http://www.foo.bar.jp/~foo/!/home/foo/public_html/!s;
my $flags = O_CREAT | O_RDWR | BINARY();
tie( %dbhash, 'SDBM_File', "$index/NMZ.sdbm.accessrank",
$flags, 0666)
or safe_die("Cannot open database $!");
chmod 0666, 'NMZ.sdbm.accessrank.dir', 'NMZ.sdbm.accessrank.pag';
if (exists($dbhash{$path})) {
$dbhash{$path}++ if ($dbhash{$path} != 2147483647);
} else {
$dbhash{$path} = 1;
}
my $nmz_uri = "$index/NMZ.field.uri";
my $nmz_access_rank = "$index/NMZ.field.accessrank";
open(NMZ_URI, "< $nmz_uri") or safe_die("Cannot open file $!");
binmode NMZ_URI;
open(NMZ_ACCESS_RANK, "> $nmz_access_rank.$$.tmp")
or safe_die("Cannot open file $!");
binmode NMZ_ACCESS_RANK;
open(NMZ_ACCESS_RANK_I, "> $nmz_access_rank.i.$$.tmp")
or safe_die("Cannot open file $!");
binmode NMZ_ACCESS_RANK_I;
chmod 0666, "$nmz_access_rank.$$.tmp",
"$nmz_access_rank.i.$$.tmp";
my $offset = 0;
while(my $uri = <NMZ_URI>) {
my $count;
chomp $uri;
if (exists($dbhash{$uri})) {
$count = $dbhash{$uri};
} else {
$count = 0;
}
printf NMZ_ACCESS_RANK "%-10d\n", $count;
print NMZ_ACCESS_RANK_I pack('N', $offset);
$offset += 11;
}
close(NMZ_ACCESS_RANK_I);
close(NMZ_ACCESS_RANK);
rename("$nmz_access_rank.$$.tmp", "$nmz_access_rank");
rename("$nmz_access_rank.i.$$.tmp", "$nmz_access_rank.i");
close(NMZ_URI);
untie( %dbhash );
print "Location: $uri\n\n";
sub BINARY {
return O_BINARY if $Config{osname} =~ /^(MS)?Win/;
}
sub safe_die($)
{
my ($msg) = @_;
open(OUT, ">> $index/error.txt");
print $msg . "\n";
close(OUT);
print "Content-Type: text/plain\n\n";
print "Error: $msg\n";
exit 1;
}
検索結果をアクセスランキング順にソートする方法(4) ― 2006年03月23日 11時45分09秒
ここで示したアクセスランキング順にソートする方法は簡易なサンプルのため、以下のような制限があります。
- エラー処理は十分ではありません。プログラムを参考に、必要なエラー処理を追加して使ってください。
- mknmz, gcnmz 等、インデックスを書き換えた後は直ぐに dbupdate.pl を実行して NMZ.filed.accessrank を更新する必要があります。
- ロックは行っていません。
- カウンタをリセットするには、NMZ.sdbm.accessrank.* を削除してください。
- SDBM を使用しているため、レコード数(文書数)が非常に多いと正常動作しないかもしれません。
- SDBM を使用しているため、キーである uri の長さが約900文字以上には対応していません。
- 文書数が多い場合、処理に時間がかかることが予想されます。
- Windows に対応するように設計していますが、動作確認していません。バグがあり Windows では動作しないかもしれません。
- 日本語のパス名には対応していません。
最近のコメント