15.3. Поиск по индексу
Пред. | Глава 15. Zend_Search | След.

## 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. За подробностями см. раздел Расширяемость. Алгоритмы ранжирования.

Пред. | Уровень выше | След.
15.2. Индексация | Начало | 15.4. Типы запросов