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