0

私の問題の簡単な要約、ワイルドカード演算子は期待した結果を返さないようです。これをいくつかのフィールドに対してテストしていKeywordます。

ここに問題を示すサンプルがあります

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;
}

これにより、期待した最後の 2 つのドキュメントではなく、一連のドキュメント全体が返されます。

出力:

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

ここで、lucene (その場合は Zend_Lucene) が最初のドキュメントと一致する理由について質問しKeywordます。フィールドはトークン化されていないと思いました。

PS: なぜ私がこのテストを実行しているのか知りたい人のために。いくつかのデータベースを備えた e コマース Web サイトがあり、カテゴリ テーブルにはいくつかのパス フィールドがあります。たとえば、カテゴリにこのパス「/1/2/3」がある場合、これは、ID 3 のカテゴリであり、親カテゴリがインデックス 2 などであることを意味します ...

問題は、ユーザーが全文検索を行ってカテゴリを指定するときです。理想的には、そのカテゴリだけでなく子カテゴリからの結果も返したいので、パス LIKE '/1/2%' を実行する lucene の方法が必要です。

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

アイデアのある方、大歓迎です。

4

1 に答える 1

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;
}
于 2010-12-02T15:14:54.693 に答える