id:tasukuchanさんにSennaのSEN_INDEX_DELIMITEDを実装していただいたので、試す。
MySQLを用意するのが面倒なので、Senna.pmで試すことにする。
XSというかCをほとんど知らないので間違っていたら指摘してくださいです。
まずpatch
- Senna.xsにSEN_INDEX_DELIMITEDとmysql風queryメソッド追加
- SEN_INDEX_DELIMITEDとqueryの簡易テストのt/04-delim.tを追加
- NGRAM onlyのcreateはエラーになるようなので修正
ファイルは以下
http://nomadscafe.jp/tmp/Senna-0.11.patch
queryのテストとして、前回と同じデータを入れて以下を作って実行
スクリプトはエレガントじゃないけど気にしない。
Senna.pmをいちいちインストールは面倒なので、このファイルをSenna.pmのdistディレクトリにいれて実行します。
#!/usr/bin/perl
use strict;
use warnings;
use FindBin;
use lib ($FindBin::Bin,"$FindBin::Bin/lib","$FindBin::Bin/blib/lib","$FindBin::Bin/blib/arch");
use Senna::Index qw(:all);
use Text::Tags::Parser;
use Encode;
use File::Spec;
my @tags = (
q/task femo/, #1
q/femo mail task/, #2
q/task femo/, #3
q/task plagger/, #4
q/task 2006-03-27 "perl monger"/, #5
q/task 終了/, #6
q/feedback femo task dev/, #7
q/task feeder dev/, #7
q/femo task dev/ #8
);
my $index_name = 'test-delimited.db';
my $path = File::Spec->catfile($index_name);
my $index = Senna::Index->create($path, SEN_VARCHAR_KEY, SEN_INDEX_DELIMITED);
my $i = 1;
for my $tags (@tags){
my @unpacks;
$tags = Encode::decode_utf8($tags);
for my $tag (Text::Tags::Parser->new->parse_tags($tags)) {
push @unpacks, &normalize($tag);
}
$index->put($i, join(' ', @unpacks));
$i++;
}
for my $q (qw/task femo 終了/,"perl monger",{
plus => [qw/task femo/],
minus => [qw/終了/]
}){
print &querize($q),",\n";
my $cur = $index->query(&querize($q));
while (my $r = $cur->next) {
printf("%s\n", $r->key);
}
}
sub querize{
my $obj = shift;
return "*E-1 ".&normalize($obj) unless ref $obj;
$obj->{plus} ||= [];
$obj->{minus} ||= [];
my $plus = join " " , map { "+" . &normalize($_) } @{$obj->{plus}};
my $minus = join " " , map { "-" . &normalize($_) } @{$obj->{minus}};
return join " " , "*E-1", $plus, $minus;
}
sub normalize{
my $str = shift;
$str = Encode::decode_utf8($str) unless utf8::is_utf8 $str;
return join 'x', map { sprintf("%02x",$_) }
unpack("U*", $str);
}
*E-1は完全一致検索のみを行うというプラグマ。詳しくはここ
結局unpackしているのは、"perl monger"の様に間にスペースを含むものもあるからです。
実行すると、
+74x61x73x6b +66x65x6dx6f -7d42x4e86
1
2
3
7
9
っていうのが最後にでます。
これは、「task」と「femo」を含んで「終了」を含まない、という条件で検索した結果で、前回と同じになってます。
ってことで、SEN_INDEX_DELIMITEDはイケテそうです。
問題はMySQLの移行かぁ。