15.3. Поиск по индексу

15.3.1. Построение запросов

Производить поиск по индексу можно двумя способами. Первый способ использует парсер запросов для построения запросов из строки. Второй способ дает возможность создавать свои запросы через программный интерфейс Zend_Search_Lucene.

Перед тем, как выбрать использование парсера запросов, пожалуйста, учтите следующее:

  1. Если вы программно генерируете строку запроса и затем парсите ее с помощью парсера запросов, то вам следует серьезно подумать о построении запросов непосредственно через программный интерфейс. Другими словами, парсер запросов предназначен для текста, вводимого пользователем, а не генерируемого программным способом.
  2. Не разбитые на лексемы поля лучше добавлять непосредственно в запросы, а не через парсер запросов. Если значения полей программно генерируются приложением, то должны быть отдельные элементы запроса для этого поля. Анализатор, используемый парсером запросов, предназначен для преобразования введенного пользователем текста в элементы запроса. Программно генерируемые значения, такие, как даты, ключевые слова и т.д., должны генерироваться единообразно.
  3. В форме запроса поля с основным текстом должны использовать парсер запросов. Все остальные, такие, как периоды времени, ключевые слова и т.д, лучше добавлять непосредственно через программный интерфейс для запросов. Поля с ограниченным набором значений, которые могут отображаться в виде выпадающего списка, лучше не добавлять в строку запроса, которая парсится, а как элемент запроса.

Оба способа используют один и тот же метод программного интерфейса для поиска в индексе.

<?php

require_once('Zend/Search/Lucene.php');

$index = new Zend_Search_Lucene('/data/my_index');

$index->find($query);

?>   

Метод Zend_Search_Lucene::find() автоматически определяет тип ввода и использует парсер запросов для построения соответствующего объекта Zend_Search_Lucene_Search_Query.

Важно отметить, что find() является чувствительным к регистру. По умолчанию LuceneIndexCreation.jar приводит все документы к нижнему регистру. Это может быть отключено через командную строку (наберите LuceneIndexCreation.jar без аргументов для получения справки). Регистр, в котором находится текст, передаваемый find(), должен соответствовать тому регистру, что есть в индексе. Если индекс приведен к нижнему регистру, то весь текст, передаваемый find(), должен быть обработан функцией strtolower(), иначе соответствия может не быть.

15.3.2. Результаты поиска

Результаты поиска являются массивом объектов Zend_Search_Lucene_Search_QueryHit. Каждый из них имеет два свойства: $hit->document является номером документа в индексе, и $hit->score, который является рангом результата поиска. Результаты упорядочены по рангу (результаты с наивысшим рангом идут первыми).

Объект Zend_Search_Lucene_Search_QueryHit также предоставляет все поля Zend_Search_Lucene_Document, представляюшего собой найденный документ. Например, соответствующий документ имеет два поля: title (название) и author (автор).

<?php

require_once('Zend/Search/Lucene.php');

$index = new Zend_Search_Lucene('/data/my_index');

$hits = $index->find($query);

foreach ($hits as $hit) {
    echo $hit->id;
    echo $hit->score;

    echo $hit->title;
    echo $hit->author;
}

?>

При необходимости исходный объект Zend_Search_Lucene_Document (документ) может быть получен из Zend_Search_Lucene_Search_QueryHit. Вы можете извлечь сохраненные в индексе части документа, используя метод getDocument() объекта индекса, и затем получить их через метод getFieldValue().

<?php

require_once('Zend/Search/Lucene.php');

$index = new Zend_Search_Lucene('/data/my_index');

$hits = $index->find($query);
foreach ($hits as $hit) {
    // возвращает объект для этого "хита"
    echo $document = $hit->getDocument();

    // возвращает объект Zend_Search_Lucene_Field
    // из Zend_Search_Lucene_Document
    echo $document->getField('title');

    // возвращает строковое значение объекта Zend_Search_Lucene_Field
    echo $document->getFieldValue('title');

    // делает то же самое, что и getFieldValue()
    echo $document->title;
}

?>   

Поля, доступные через объект Zend_Search_Lucene_Document, определяются во время индексирования. Поля документа либо только индексируются, либо индексируются и сохраняются в индексе индесирующим приложением (например, LuceneIndexCreation.jar).

Обратите внимание, что идентификатор документа (в нашем примере -- 'path') также сохраняется в индексе и должен извлекаться из него.

15.3.3. Ранжирование результата

Zend_Search_Lucene использует тот же самый алгоритм ранжирования, что и Java Lucene. Результаты поиска упорядочиваются по рангу (релевантности). "Хиты" с наибольшим рангом идут первыми.

Различные ранги результатов означают, что один документ больше соответствует запросу, чем другой.

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

Число, соответствующее рангу, может быть получено через свойство score:

<?php
$hits = $index->find($query);

foreach ($hits as $hit) {
    echo $hit->id;
    echo $hit->score;
}

?>   

Для вычисления ранга используется класс Zend_Search_Lucene_Search_Similarity. За подробностями см. раздел Расширяемость. Алгоритмы ранжирования.