Zend Search Lucene — поиск по определенному полю

В настоящее время я установил Zend_Search_Lucene в качестве поисковой системы в проекте, над которым я работаю.

Он отлично работает на уровне по умолчанию (т.е. поиск по всем полям), однако теперь мне нужно выполнить поиск в определенном поле.

Причина этого в том, что я пытаюсь закодировать возможность работы с орфографическими ошибками. Поэтому я добавляю звуковое выражение каждого слова в заголовке документа.

Например:

$productArray['title'] = 'June Monthly Meat Box';  
$doc = new Zend_Search_Lucene_Document();  
$doc->addField(Zend_Search_Lucene_Field::text('product_title', $productArray['title']));  
$soundex = implode(' ',  array_map('soundex', array_map('trim', preg_split('/ /', $productArray['title'], NULL, PREG_SPLIT_NO_EMPTY))));  
$doc->addField(Zend_Search_Lucene_Field::keyword('soundex', $soundex));  
$index->addDocument($doc);

Это добавляет «J500 M534 M300 B200» в качестве поля soundex.

Вот как выполняется поиск:

$queryString = trim(urldecode($this->_request->getParam('q')));  
$words = array_map('trim', preg_split('/ /', $queryString, NULL, PREG_SPLIT_NO_EMPTY));    

$query = new Zend_Search_Lucene_Search_Query_Boolean();  
$subquery1 = new Zend_Search_Lucene_Search_Query_MultiTerm();  
foreach($words as $word) 
{  
    $subquery1->addTerm(new Zend_Search_Lucene_Index_Term($word));  
}  

$subquery2 = new Zend_Search_Lucene_Search_Query_MultiTerm();  
foreach($words as $word)
{  
        $subquery2->addTerm(new Zend_Search_Lucene_Index_Term(strtolower(soundex($word)), 'soundex'));  
}  
$query->addSubquery($subquery1);  
$query->addSubquery($subquery2);  

Переменная $subquery1 хранит каждое слово исходного запроса (это работает само по себе)
Переменная $subquery2 хранит звуковое выражение каждого слова. План состоит в том, чтобы искать поле для звукового выражения, а также другие поля для каждого слова. Поэтому, если кто-то ошибся в написании «мясо» с «maet», он вернет результат, поскольку звуковое выражение будет таким же для «M300».

Я использую Luke для просмотра набора данных и вижу правильные термины. Когда я использую Luke для поиска soundex (т.е. soundex:M300), он не возвращает результатов, однако, если я ищу все поле (т.е. soundex:"J500 M534 M300 B200"), он возвращает правильный документ.

Что происходит, чтобы предотвратить поиск в поле?


person Mark Smith    schedule 03.05.2012    source источник


Ответы (1)


Если я правильно понимаю Zend_Search_Lucene_Field::keyword (то, что вы использовали для «soundex» выше), он предназначен для хранения одного значения за раз (например, одной даты или одного URL).

Я думаю, что для поля «soundex» вы хотите вместо этого использовать метод хранения токенов, такой как Zend_Search_Lucene_Field::text, поскольку похоже, что вы хотите искать отдельные токены в поле «soundex», а не только значение всего поля.

person Mark Leighton Fisher    schedule 08.05.2012
comment
Привет Марк, Спасибо за информацию. Первоначально у меня было это как текстовое поле, но я изменил его. Причина изменения заключалась в том, что Люк отображал термины с самым высоким рейтингом для поля soundex одной буквой (например: b, s, r и т. д.). Поэтому, если я ищу soundex:m, я вывожу все результаты, где есть soundex MXXX. Что мне кажется странным, так это то, что в терминах нет цифр. Игнорируются ли числа для токенизированных полей? - person Mark Smith; 08.05.2012
comment
Разобравшись, мне пришлось изменить анализатор по умолчанию, так как я узнал, что он не рассматривает числа как часть терминов. Я добавил Zend_Search_Lucene_Analysis_Analyzer::setDefault( new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive() ); перед созданием индекса и перед поиском в индексе. - person Mark Smith; 08.05.2012