SEN_INDEX_DELIMITED
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の移行かぁ。
コメント
おお、いけてましたか。。。
よかったよかった。
投稿者: tasuku
|
2006年04月02日 03:09
パッチ、取り込んでいいですか?
投稿者: daisuke | 2006年04月02日 18:02
> daisukeさん
問題なかったら、よろしくおねがいします。
投稿者: かぜぶろ
|
2006年04月02日 20:24
なんかquery()で直したというNGRAM関係の問題が再現できません。再現できるテストをいただけますか?
ちょっとそれ以外の問題もあったので先に0.12出しますね
投稿者: daisuke | 2006年04月02日 21:04
queryの部分ではないです。
sennaの方がリビジョン106で
t/03-ngram.tで、
my $index = Senna::Index->create($path, SEN_VARCHAR_KEY, SEN_INDEX_NGRAM);
のままだと、
t/01-sanity....ok
t/02-morph.....ok
t/03-ngram.....dubious
Test returned status 0 (wstat 11, 0xb)
t/04-delim.....ok
Failed Test Stat Wstat Total Fail Failed List of Failed
-------------------------------------------------------------------------------
t/03-ngram.t 0 11 ?? ?? % ??
Failed 1/4 test scripts, 75.00% okay. -2/61 subtests failed, 103.28% okay.
になります。
投稿者: かぜぶろ
|
2006年04月02日 22:55
SEN_INDEX_NORMALIZE | SEN_INDEX_NGRAM
にすると、make test通るみたいっすね。
投稿者: かぜぶろ
|
2006年04月02日 23:06
http://search.cpan.org/src/DMAKI/Senna-0.12/t/05-delim.t
テストがそのまま採用された。しまったorz
投稿者: かぜぶろ
|
2006年04月03日 02:12
index_create時にSEN_INDEX_NGRAMのみを指定して、
SEN_INDEX_NORMALIZE を指定しない場合にエラーが発生する不具合は
rev109で修正されましたー。
投稿者: グニャラくん | 2006年04月03日 09:13
ありゃ、テストだめ?よくみてなかったけど、動いているしいいかと思って。
ちなみにquery()用のテストってあります?
投稿者: daisuke | 2006年04月03日 16:52
テストのサンプル文がネタっぽくなっているだけです。
queryのテストはないっすね。
05-delimをちょっと弄ればいいような気がする。
投稿者: かぜぶろ
|
2006年04月04日 14:08