# Обзор

## Введение

Zend_Search_Lucene является поисковым движком общего назначения для полнотекстового поиска, написанным полностью на PHP 5. Так как он хранит индекс в файловой системе и не требует наличия сервера баз данных, то дает возможность реализовать поиск практически для всех веб-сайтов, работающих под управлением PHP. Zend_Search_Lucene поддерживает следующие возможности:

- Ранжированный поиск — более подходящие результаты возвращаются первыми

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

- Поиск по определенному полю (например: заголовок, автор, содержимое)

Zend_Search_Lucene произошел от проекта Apache Lucene. За более подробной информацией см. .

## Объекты документа и поля

Zend_Search_Lucene оперирует с документами как с элементарными объектами для индексации. Документ делится на именованные поля, содержащие контент, по которому может производиться поиск.

Документ представлен объектом Zend_Search_Lucene_Document, этот объект содержит объекты Zend_Search_Lucene_Field, представляющие собой поля документа.

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

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

Класс `Zend_Search_Lucene_Field` предоставляет несколько статических методов для создания полей с различными характеристиками.

    <?php
    $doc = new Zend_Search_Lucene_Document();

    // Данные поля не разбиваются на лексемы,
    // но индексируются и полностью сохраняются в индексе.
    // Сохраненные данные поля могут быть получены из индекса.
    $doc->addField(Zend_Search_Lucene_Field::Keyword('doctype',
                                                     'autogenerated'));

    // Данные поля не разбиваются на лексемы и не индексируются,
    // но полностью сохраняются в индексе.
    $doc->addField(Zend_Search_Lucene_Field::UnIndexed('created',
                                                       time()));

    // Бинарное поле, данные которого не разбиваются на лексемы и не индексируются,
    // но сохраняются в индексе.
    $doc->addField(Zend_Search_Lucene_Field::Binary('icon',
                                                    $iconData));

    // Данные поля разбиваются на лексемы, индексируются
    // и полностью сохраняются в индексе.
    $doc->addField(Zend_Search_Lucene_Field::Text('annotation',
                                                  'Document annotation text'));

    // Данные поля разбиваются на лексемы и индексируются,
    // но не сохраняются в индексе.
    $doc->addField(Zend_Search_Lucene_Field::UnStored('contents',
                                                      'My document content'));

    ?>

Каждый из этх методов (исключая метод `Zend_Search_Lucene_Field::Binary()`) имеет необязательный параметр `$encoding`. Через него указывается кодировка для входных данных.

Кодировка может различаться как для документов, так и для полей в одном документе.

    <?php
    $doc = new Zend_Search_Lucene_Document();
    $doc->addField(Zend_Search_Lucene_Field::Text('title', $title, 'iso-8859-1'));
    $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $contents, 'utf-8'));
    ?>

Если этот параметр опущен, то используется текущая локаль. Например:

    <?php
    setlocale(LC_ALL, 'de_DE.iso-8859-1');
    ...
    $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $contents));
    ?>

Поля всегда сохраняются и возвращаются из индекса в кодировке UTF-8. Преобразование в UTF-8 производится автоматически.

Анализатор текста (см. далее) может также преобразовывать текст в другие кодировки. В настоящее время используемый по умолчанию анализатор преобразует текст в кодировку 'ASCII//TRANSLIT'. Имейте в виду, что такое преобразование может зависеть от текущей локали.

Имена полей могут быть любыми.

Java Lucene по умолчанию использует для поиска поле "contents". Zend_Search_Lucene по умолчанию производит поиск по всем полям, но это поведение можно изменить. За подробностями см. Поля для поиска.

## Значение типов полей

- Поля `Keyword` полностью сохраняются и индексируются, это означает, что можно не только производить поиск в них, но и отображать их в результатах поиска. Они не делятся на отдельные слова посредством разбиения на лексемы. Нумерованные поля БД обычно преобразуются в поля Keyword в Zend_Search_Lucene.

- В полях `UnIndexed` нельзя производить поиск, но они возвращаются в результатах поиска. Поля timestamp, ключевые поля, пути в файловой системе и другие внешние идентификаторы — хорошие кандидаты для того, чтобы быть полями UnIndexed.

- Поля `Binary` не разбиваются на лексемы и не индексируются, но сохраняются для возвращения в результатах поиска. Они могут использоваться для хранения любых данных, закодированных в виде бинарной строки — как, например, иконки.

- Поля `Text` сохраняются, разбиваются на лексемы и индексируются. Текстовые поля подходят для хранения такой информации, как темы и заголовки — в них нужно не только искать, но и возвращать с результатами поиска.

- Поля `UnStored` разбиваются на лексемы и индексируются, но не сохраняются в индексе. Тексты большого объема лучше индексировать, используя этот тип поля. Хранение таких данных создает индекс, который занимает много места на диске, поэтому если нужно искать в данных, но не выводить их, то используйте поле UnStored. Поля UnStored полезны, когда используется индекс Zend_Search_Lucene в комбинации с реляционной БД. Вы можете индексировать большие поля данных для поиска с помощью UnStored и извлекать их из реляционной БД, используя отдельные поля как идентификаторы.

  ### Типы Zend_Search_Lucene_Field

  Тип поля | Сохраняется | Индексируется | Разбивается на лексемы | Бинарное
  --- | --- | --- | --- | ---
  Keyword | Да | Да | Нет | Нет
  UnIndexed | Да | Нет | Нет | Нет
  Binary | Да | Нет | Нет | Да
  Text | Да | Да | Да | Нет
  UnStored | Нет | Да | Да | Нет

## HTML-документы

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

    <?php
    $doc = Zend_Search_Lucene_Document_Html::loadHTMLFile($filename);
    $index->addDocument($doc);
    ...
    $doc = Zend_Search_Lucene_Document_Html::loadHTML($htmlString);
    $index->addDocument($doc);
    ?>

Класс `Zend_Search_Lucene_Document_Html` использует методы `DOMDocument::loadHTML()` и `DOMDocument::loadHTMLFile()` для парсинга исходного HTML-кода, поэтому HTML не обязательно должен быть правильно сформированным или быть XHTML. С другой стороны, он чувствителен к кодировке, указанной в теге "meta http-equiv" заголовка.

Класс `Zend_Search_Lucene_Document_Html` распознает заголовок, тело документа и его мета-теги.

Поле 'title' будет содержать значение из /html/head/title. Оно сохраняется в индексе, разбивается на лексемы и его содержимое доступно для поиска.

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

Методы `loadHTML()` и `loadHTMLFile()` класса `Zend_Search_Lucene_Document_Html` также имеют второй необязательный аргумент. Если он установлен в true, то содержимое тела документа сохраняется в индексе и может быть получено из индекса. По умолчанию тело документа разбивается на лексемы и индексируется, но не сохраняется в индексе.

К мета-тегам заголовка документа создаются дополнительные поля. При этом имя поля берется из атрибута 'name', содержимое поля - из атрибута 'content', это содержимое разбивается на лексемы, индексируется и сохраняется в индексе, и, таким образом, документы можно будет искать по их мета-тегам - например, по ключевым словам (keywords).

К сгенерированным документам можно добавлять любые другие поля.

    <?php
    $doc = Zend_Search_Lucene_Document_Html::loadHTML($htmlString);
    $doc->addField(Zend_Search_Lucene_Field::UnIndexed('created',
                                                       time()));
    $doc->addField(Zend_Search_Lucene_Field::UnIndexed('created',
                                                       time()));
    $doc->addField(Zend_Search_Lucene_Field::Text('annotation',
                                                  'Document annotation text'));
    $index->addDocument($doc);
    ?>

Линки из исходного документа не добавляются в генерируемый документ, но могут быть получены через методы `Zend_Search_Lucene_Document_Html::getLinks()` и `Zend_Search_Lucene_Document_Html::getHeaderLinks()`:

    <?php
    $doc = Zend_Search_Lucene_Document_Html::loadHTML($htmlString);
    $linksArray = $doc->getLinks();
    $headerLinksArray = $doc->getHeaderLinks();
    ?>