Странности Zend_Lucene и оператора подстановочных знаков

Краткое изложение моей проблемы: оператор подстановочных знаков, похоже, не возвращает результат, который я ожидаю. Я тестирую это на некотором поле 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;
}

Это вернет весь набор документов вместо двух последних, как я ожидал.

выход:

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

Итак, вот мой вопрос, почему lucene (в данном случае Zend_Lucene) соответствует первым документам, я думал, что поля Keyword не токенизированы.

PS: для тех, кто хочет знать, почему я провожу этот тест. У меня есть веб-сайт электронной коммерции с некоторой базой данных, в таблице категорий есть поле пути. Например, у категории может быть этот путь «/1/2/3», что означает, что это категория с идентификатором 3, а родительская категория имеет индекс 2 и т. д.

Проблема в том, что когда пользователь выполняет полнотекстовый поиск и указывает категорию, в идеале я хочу вернуть результаты из этой категории, а также из дочерних категорий, поэтому мне нужен lucene способ сделать путь LIKE '/1/2%'.

Еще одна возможность - объединить результаты SQL-запроса и попаданий lucene, если это возможно, я бы хотел избежать этого случая, потому что он может работать плохо.

Если у вас есть идеи, добро пожаловать.


person RageZ    schedule 02.12.2010    source источник


Ответы (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;
}
person rik    schedule 02.12.2010
comment
Спасибо за ответы работает. Я так понимаю, lucene убирала цифры из-за анализатора. После того, как я не могу объяснить, почему замена / на букву слова что-то меняет, поле ключевого слова не должно быть токенизировано, верно? - person RageZ; 03.12.2010
comment
Поля ключевых слов не токенизированы, это правда. Но поисковый запрос есть. - person rik; 03.12.2010