2010-12-02 11 views
0

私の問題の簡単な要約は、ワイルドカード演算子は私が期待している結果を返すようには見えません。私はこれをいくつかのKeywordフィールドに対してテストしています。ここでZend_Luceneとwilcardオペレータの奇妙さ

問題を示すサンプルを来

include 'Zend/Loader/Autoloader.php'; 
$autoloader = Zend_Loader_Autoloader::getInstance(); 
$autoloader->setFallbackAutoloader(true); 


Zend_Search_Lucene_Analysis_Analyzer::setDefault(
    new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8_CaseInsensitive()); 
@mkdir('/tmp/test-lucene'); 
$index = Zend_Search_Lucene::create('/tmp/test-lucene'); 
$doc = new Zend_Search_Lucene_Document(); 
$doc->addField(Zend_Search_Lucene_Field::Keyword('path', 'root/1/2/3')); 
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents', 'The lazy fox jump over the dog bla bla bla')); 
$index->addDocument($doc); 


$doc = new Zend_Search_Lucene_Document(); 
$doc->addField(Zend_Search_Lucene_Field::Keyword('path', 'root/1')); 
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents', 'The lazy fox jump over the dog bla bla bla')); 
$index->addDocument($doc); 

$doc = new Zend_Search_Lucene_Document(); 
$doc->addField(Zend_Search_Lucene_Field::Keyword('path', 'root/3/2/1')); 
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents', 'The lazy fox jump over the dog bla bla bla')); 
$index->addDocument($doc); 

$doc = new Zend_Search_Lucene_Document(); 
$doc->addField(Zend_Search_Lucene_Field::Keyword('path', 'root/3/2/2')); 
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents', 'The lazy fox jump over the dog bla bla bla')); 
$index->addDocument($doc); 

$hits = $index->find('path:root/3/2*'); 
foreach($hits as $hit){ 
    $doc = $hit->getDocument(); 
    echo $doc->getFieldValue('path') . PHP_EOL; 
} 

この代わりに私が期待しますように最後の二つの文書のセット全体を返します

出力:だからここ

root/1/2/3 
root/1 
root/3/2/1 
root/3/2/2 

なぜlucene(その場合はZend_Lucene)が最初の文書と一致するのか、私はKeywordフィールドはトークン化されていないと思った。

PS:なぜこのテストを実行しているのか知りたいと思う人のために。私はいくつかのデータベースを持つeコマースのウェブサイトを持っています、カテゴリテーブルはいくつかのパスフィールドを持っています。たとえば、カテゴリには、このパス '/ 1/2/3'があります。つまり、ID 3のカテゴリ、親カテゴリはインデックス2などです。

問題は、フルテキスト検索とカテゴリを指定すると、理想的にはそのカテゴリの結果だけでなく、子カテゴリも返されたいので、私はLIKE '/ 1/2%'のようなルーメンの方法を必要とします。

もう1つの可能性は、SQLクエリとluceneヒットの結果をマージすることです。可能であれば、パフォーマンスが低下する可能性があるため、このケースを避けたいと思います。

ご意見がありましたら、歓迎されます。

答えて

1

Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitiveを使用し、スラッシュをパスには現れないがZend_Search_Luceneの単語文字に置き換えます。私はドイツ語ßを使いました。

include 'Zend/Loader/Autoloader.php'; 
$autoloader = Zend_Loader_Autoloader::getInstance(); 
$autoloader->setFallbackAutoloader(true); 

Zend_Search_Lucene_Analysis_Analyzer::setDefault(
    new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()); 
@mkdir('/tmp/test-lucene'); 
$index = Zend_Search_Lucene::create('/tmp/test-lucene'); 

foreach (array('root/1/2/3', 'root/1', 'root/3/2/1', 'root/3/2/2') as $path) { 
    $path = str_replace('/', 'ß', $path); 
    $doc = new Zend_Search_Lucene_Document(); 
    $doc->addField(Zend_Search_Lucene_Field::Keyword('path', $path)); 
    $index->addDocument($doc); 
} 

$hits = $index->find(str_replace('/', 'ß', 'path:root/3/2*')); 
foreach($hits as $hit){ 
    echo str_replace('ß', '/', $hit->getDocument()->getFieldValue('path')) . PHP_EOL; 
} 
+0

回答ありがとうございます。私はルーネンがアナライザのために数字を取り除いていたので参照してください。私は本当になぜ/単語の文字の変更で何かを置き換える理由を説明することはできません、キーワードフィールドは右にトークン化すべきではない? – RageZ

+0

キーワードフィールドはトークン化されていません。しかし、検索クエリはです。 – rik

+0

良い点は、それを説明する – RageZ