# Индексация

## Создание нового индекса

Возможности по созданию и обновлению индекса реализованы в модуле Zend_Search_Lucene и Java Lucene. Вы можете использовать обе эти возможности.

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

    <?php
    // Создание индекса
    $index = Zend_Search_Lucene::create('/data/my-index');

    $doc = new Zend_Search_Lucene_Document();

    // Сохранение URL документа для того, чтобы идентифицировать его
    // в результатах поиска
    $doc->addField(Zend_Search_Lucene_Field::Text('url', $docUrl));

    // Индексирование содержимого документа
    $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $docContent));

    // Добавление документа в индекс
    $index->addDocument($doc);
    ?>

Только что добавленные документы можно сразу извлекать из индекса.

## Обновление индекса

Та же самая процедура используется при обновлении существующего индекса. Единственное отличие состоит в том, что вместо метода create() вызывается метод open():

    <?php
    // Открытие существующего индекса
    $index = Zend_Search_Lucene::open('/data/my-index');

    $doc = new Zend_Search_Lucene_Document();
    // Сохраниение URL документа для того, чтобы идентифицировать его в результатах поиска.
    $doc->addField(Zend_Search_Lucene_Field::Text('url', $docUrl));
    // Индексация содержимого документа.
    $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $docContent));

    // Добавление документа в индекс.
    $index->addDocument($doc);
    ?>

## Обновление документов

Формат файлов индекса Lucene не поддерживает обновление документов. Для обновления документ должен быть удален и добавлен снова.

Метод `Zend_Search_Lucene::delete()` оперирует с внутренним идентификатором индекса документа. Он может быть получен из результата запроса ("хит") через свойство 'id':

    <?php
    $removePath = ...;
    $hits = $index->find('path:' . $removePath);
    foreach ($hits as $hit) {
        $index->delete($hit->id);
    }
    ?>

## Получение размера индекса

В Zend_Search_Lucene есть два способа получения размера индекса.

Метод `Zend_Search_Lucene::maxDoc()` возвращает число, на единицу большее, чем наибольший возможный номер документа. Фактически это общее количество документов в индексе, включая удаленные. У этого метода есть синоним - `Zend_Search_Lucene::count()`.

`Zend_Search_Lucene::numDocs()` возвращает общее количество не удаленных документов.

    <?php
    $indexSize = $index->count();
    $documents = $index->numDocs();
    ?>

Метод `Zend_Search_Lucene::isDeleted($id)` может использоваться для проверки того, был ли документ удален.

    <?php
    for ($count = 0; $count < $index->maxDoc(); $count++) {
        if ($index->isDeleted($count)) {
            echo "Document #$id is deleted.\n";
        }
    }
    ?>

При оптимизации индекса производится очищение индекса от удаленных документов и сжатие диапазона используемых идентификаторов. Поэтому внутренний идентификатор документа может изменяться

## Оптимизация индекса

Индекс Lucene состоит из сегментов. Каждый сегмент является независимой порцией данных.

Файлы сегментов индекса Lucene по своей природе не могут обновляться. Обновление сегмента требует его полной реорганизации. За подробностями см. форматы файлов индекса (http://lucene.apache.org/java/docs/fileformats.html). Новые документы добавляются в индекс путем создания новых сегментов.

Увеличение числа сегментов ухудшает качество индекса, но оптимизация индекса восстанавливает его. Оптимизация сводится к объединению нескольких сегментов в один. Этот процедура также не обновляет сегменты. Она создает новый большой сегмент, который содержит новый оптимизированный сегмент вместо набора старых сегментов и обновляет список сегментов (файл 'segments').

Полная оптимизация индекса может производиться через вызов метода `Zend_Search_Lucene::optimize()`. Он объединяет все сегменты индекса в один.

    <?php
    // Открытие существующего индекса
    $index = Zend_Search_Lucene::open('/data/my-index');

    // Оптимизация индекса
    $index->optimize();
    ?>

Автоматическая оптимизация индекса выполняется для поддержания индекса в согласованном состоянии.

Автоматическая оптимизация является итеративным процессом, управление которым производится посредством нескольких опций. В процессе этой оптимизации очень маленькие сегменты объединяются в сегменты большего размера, затем эти сегменты объединяются в еще большие и т.д.

### Опция автоматической оптимизации MaxBufferedDocs

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

MaxBufferedDocs может быть получен или установлен через методы `$index->getMaxBufferedDocs()` и `$index->setMaxBufferedDocs($maxBufferedDocs)` соответственно.

Значение опции по умолчанию равно 10.

### Опция автоматической оптимизации MaxMergeDocs

MaxMergeDocs является наибольшим количеством документов при достижении которого они всегда объединяются методом addDocument(). Меньшие значения (т.е. меньше, чем 10.000) являются наилучшими для интерактивной индексации, так как ограничивает продолжительность пауз в течение индексации до нескольких секунд. Большие значения являются наилучшими для пакетной индексации и более быстрого поиска.

MaxMergeDocs может быть получен или установлен через методы `$index->getMaxMergeDocs()` и `$index->setMaxMergeDocs($maxMergeDocs)` соответственно.

Значение опции по умолчанию равно PHP_INT_MAX.

### Опция автоматической оптимизации MergeFactor

MergeFactor определяет, как часто сегменты индекса объединяются с помощью addDocument(). Чем менше значение, тем меньше и объем оперативной памяти, используемой в процессе индексации, и поиск по неоптимизированному индексу производится быстрее, но скорость индексации снижается. Чем больше значение, тем больше и объем используемой оперативной памяти, и индексация производится быстрее, в то время как поиск по неоптимизированному индексу производится медленнее. Таким образом, большие значения (> 10) являются наилучшими в случае пакетной индексации, а меньшие (< 10) — для индексов, которые поддерживаются интерактивно.

MergeFactor является хорошим средством оценки среднего количества сегментов, объединяемых в одном прохождении автоматической оптимизации. Слишком большие значения приводят к созданию большого количества сегментов то того, как они объединятся в один новый. Это может вызвать сообщение об ошибке "failed to open stream: Too many open files". Данное ограничение зависит от операционной системы.

MergeFactor может быть получен или установлен через методы `$index->getMergeFactor()` и `$index->setMergeFactor($mergeFactor)` соответственно.

Значение опции по умолчанию равно 10.

Lucene Java и Luke (Lucene Index Toolbox - http://www.getopt.org/luke/) также могут использоваться для оптимизации индекса.

## Ограничения

Ограничения зависят от платформы.

Для 32-битной платформы максимальный размер индекса составляет 2Гб.