Расширяемость
Анализ текста
Класс Zend_Search_Lucene_Analysis_Analyzer
используется
индексатором для разбиения текстовых полей документа на лексемы.
Методы
Zend_Search_Lucene_Analysis_Analyzer::getDefault()
и
Zend_Search_Lucene_Analysis_Analyzer::setDefault()
используются для получения и установки анализатора по умолчанию.
Таким образом, вы можете устанавливать собственный анализатор текста
или выбирать его из ряда предопределенных анализаторов:
Zend_Search_Lucene_Analysis_Analyzer_Common_Text
и
Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive
(по умолчанию). Оба интерпретируют лексему как последовательность
букв. Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive
приводит лексемы к нижнему регистру.
Переключение между анализаторами:
<?php
Zend_Search_Lucene_Analysis_Analyzer::setDefault(
new Zend_Search_Lucene_Analysis_Analyzer_Common_Text());
...
$index->addDocument($doc);
Zend_Search_Lucene_Analysis_Analyzer_Common
спроектирован для того, чтобы быть родительским классом для всех
анализаторов, определяемых пользователем. В наследующем классе
достаточно определить методы reset()
и
nextToken()
, которые берут строку из свойства $_input
и возвращают лексемы шаг за шагом (NULL означает конец
потока).
Метод nextToken()
должен использовать метод
normalize()
для каждой лексемы. Это позволит
использовать фильтры лексем с вашим анализатором.
Ниже приведен пример пользовательского анализатора, котрорый
принимает слова с цифрами как элементы:
Example #1 Собственный анализатор текста
<?php
/** Это созданный пользователем текстовый анализатор, который интерпретирует слова с цифрами как один элемент. */
/** Zend_Search_Lucene_Analysis_Analyzer hierarchy */
require_once 'Zend/Search/Lucene/Analysis/Analyzer.php';
class My_Analyzer extends Zend_Search_Lucene_Analysis_Analyzer_Common
{
private $_position;
/**
* Установка позиции в начальное состояние
*/
{
$this->_position = 0;
}
/**
* API для разбиения на лексемы
* Получение следующей лексемы
* Возвращает null, если достигнут конец потока
*
* @return Zend_Search_Lucene_Analysis_Token|null
*/
public function nextToken()
{
if ($this->_input === null) {
return null;
}
while ($this->_position <
strlen($this->_input
)) {
// пропуск пробела
while ($this->_position <
strlen($this->_input
) &&
$this->_position++;
}
$termStartPosition = $this->_position;
// чтение лексемы
while ($this->_position <
strlen($this->_input
) &&
$this->_position++;
}
// Пустая лексема, конец потока
if ($this->_position == $termStartPosition) {
return null;
}
$token = new Zend_Search_Lucene_Analysis_Token(
$termStartPosition,
$this->_position - $termStartPosition),
$termStartPosition,
$this->_position);
$token = $this->normalize($token);
if ($token !== null) {
return $token;
}
// Продолжение, если лексема пропущена
}
return null;
}
}
Zend_Search_Lucene_Analysis_Analyzer::setDefault(
new My_Analyzer());
Фильтрация лексем
Анализатор Zend_Search_Lucene_Analysis_Analyzer_Common
также предоставляет механизм фильтрации лексем.
Класс Zend_Search_Lucene_Analysis_TokenFilter
является
уровнем абстракции для таких фильтров. Он должен использоваться как
предок для ваших собственных фильтров.
Пользовательские фильтры должны реализовать метод
normalize()
, который может преобразовывать лексему или
сигнализировать, что лексема должна быть пропущена.
В предоставляемом анализаторе уже определены три фильтра:
-
Zend_Search_Lucene_Analysis_TokenFilter_LowerCase
-
Zend_Search_Lucene_Analysis_TokenFilter_ShortWords
-
Zend_Search_Lucene_Analysis_TokenFilter_StopWords
Фильтр LowerCase
уже используется для анализатора
Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive
,
который применяется по умолчанию.
ShortWords
и StopWords
могут
использоваться с уже включенными анализаторами или вашими
собственными:
<?php
$stopWords =
array('a',
'an',
'at',
'the',
'and',
'or',
'is',
'am');
$stopWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_StopWords($stopWords);
$analyzer = new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive();
$analyzer->addFilter($stopWordsFilter);
Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer);
<?php
$shortWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_ShortWords();
$analyzer = new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive();
$analyzer->addFilter($shortWordsFilter);
Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer);
Конструктор
Zend_Search_Lucene_Analysis_TokenFilter_StopWords
принимает массив стоп-слов в качестве аргумента. Но стоп-слова можно
также загружать и из файла:
<?php
$stopWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_StopWords();
$stopWordsFilter->loadFromFile($my_stopwords_file);
$analyzer = new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive();
$analyzer->addFilter($stopWordsFilter);
Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer);
Файл должен быть текстовым с одним словом в каждой строке. Символом
'#' помечаются строки с комментариями.
Конструктор
Zend_Search_Lucene_Analysis_TokenFilter_ShortWords
имеет один необязательный параметр, это ограничение длины слова.
Его значение по умолчанию равно 2.
Алгоритмы ранжирования
Ранг q документа
d определяется следующим образом:
score(q,d) = sum( tf(t in d) * idf(t) * getBoost(t.field in d) * lengthNorm(t.field in d) ) *
coord(q,d) * queryNorm(q)
tf(t in d) - Zend_Search_Lucene_Search_Similarity::tf($freq)
- коэффициент ранга, основанный на том, насколько часто встречается
элемент или фраза в документе.
idf(t) - Zend_Search_Lucene_Search_SimilaritySimilarity::tf($term, $reader)
- коэффициент ранга для простого элемента применительно к определенному
индексу.
getBoost(t.field in d) - коэффициент усиления для поля элемента.
lengthNorm($term) - значение нормализации для поля, получаемое из
общего количества элементов, содержащихся в поле. Это значение
хранится внутри индекса. Эти значения вместе с коэффициентом усиления поля
хранятся в индексе, результатом их умножения является
ранг для каждого поля.
Совпадения в длинных полях менее точны, поэтому реализации этого метода
обычно возвращают тем меньшие значения, чем
больше число лексем, и тем большие значения, чем меньше число лексем.
сoord(q,d) - Zend_Search_Lucene_Search_Similarity::coord($overlap, $maxOverlap)
- коэффициент ранга, основанный на относительной доле всех элементов запроса,
найденных в документе.
Присутствие большого количества элементов запроса означает лучшее
соответствие запросу, поэтому реализации этого метода обычно возвращают
бОльшие значения, когда соотношение между этими параметрами большое
и меньшие значения, когда соотношение между ними небольшое.
queryNorm(q) - значение нормализации для запроса, получаемое из суммы
возведенных в квадрат весов каждого из элементов запроса. Это значение
затем умножается в вес каждого элемента запроса.
Это не влияет на ранжирование, цель нормализации состоит в том, чтобы
сделать соизмеримыми ранги, полученные при различных запросах.
Алгоритм ранжирования может быть изменен через определение своего
собственного класса. Для этого надо создать потомка класса
Zend_Search_Lucene_Search_Similarity, как показано ниже, затем
использовать метод
Zend_Search_Lucene_Search_Similarity::setDefault($similarity);
для установки объекта как используемого по умолчанию.
<?php
class MySimilarity extends Zend_Search_Lucene_Search_Similarity {
public function lengthNorm($fieldName, $numTerms) {
return 1.0/
sqrt($numTerms);
}
public function queryNorm($sumOfSquaredWeights) {
return 1.0/
sqrt($sumOfSquaredWeights);
}
public function tf($freq) {
}
/**
* Сейчас не используется. Подсчитывает сумму соответствий неточной фразе,
* основанную на изменяемом расстоянии.
*/
public function sloppyFreq($distance) {
return 1.0;
}
public function idfFreq($docFreq, $numDocs) {
return log($numDocs/
(float
)($docFreq+1)) +
1.0;
}
public function coord($overlap, $maxOverlap) {
return $overlap/(float)$maxOverlap;
}
}
$mySimilarity = new MySimilarity();
Zend_Search_Lucene_Search_Similarity::setDefault($mySimilarity);
?>
Контейнеры хранения
Абстрактный класс Zend_Search_Lucene_Storage_Directory
определяет функционал директории.
Конструктор Zend_Search_Lucene
использует строку или
объект Zend_Search_Lucene_Storage_Directory
как входные данные.
Zend_Search_Lucene_Storage_Directory_Filesystem
реализует
функционал директории для файловой системы.
Если для конструктора Zend_Search_Lucene
в качестве входных
данных испольуется строка, то считыватель индекса (объект
Zend_Search_Lucene
) рассматривает ее как путь в файловой
системе и сама инстанцирует объекты
Zend_Search_Lucene_Storage_Directory_Filesystem
.
Вы можете определить собственную реализацию директории,
создав потомка класса Zend_Search_Lucene_Storage_Directory
.
Методы Zend_Search_Lucene_Storage_Directory
:
<?php
abstract class Zend_Search_Lucene_Storage_Directory {
/**
* Закрывает средство хранения.
*
* @return void
*/
abstract function close();
/**
* Создает новый пустой файл с данным именем в директории.
*
* @param string $name
* @return void
*/
abstract function createFile($filename);
/**
* Удаляет существующий файл в директории.
*
* @param string $filename
* @return void
*/
abstract function deleteFile($filename);
/**
* Возвращает true, если файл с данным именем существует.
*
* @param string $filename
* @return boolean
*/
abstract function fileExists($filename);
/**
* Возвращает длину файла в директории.
*
* @param string $filename
* @return integer
*/
abstract function fileLength($filename);
/**
* Возвращает время последнего изменения файла в формате UNIX.
*
* @param string $filename
* @return integer
*/
abstract function fileModified($filename);
/**
* Переименовывает существующий файл в директории.
*
* @param string $from
* @param string $to
* @return void
*/
abstract function renameFile($from, $to);
/**
* Устанавливает время изменения файла в текущее.
*
* @param string $filename
* @return void
*/
abstract function touchFile($filename);
/**
* Возвращает объект Zend_Search_Lucene_Storage_File для данного файла в директории.
*
* @param string $filename
* @return Zend_Search_Lucene_Storage_File
*/
abstract function getFileObject($filename);
}
?>
Метод getFileObject($filename)
класса
Zend_Search_Lucene_Storage_Directory
возвращает
объект Zend_Search_Lucene_Storage_File
.
Абстрактный класс Zend_Search_Lucene_Storage_File
реализует
абстракцию файла и примитивы чтения файла индекса.
Вы должны создать класс, наследующий от Zend_Search_Lucene_Storage_File
для своей реализации директории.
Только два метода класса Zend_Search_Lucene_Storage_File
должны быть
перегружены в вашей реализации:
<?php
class MyFile extends Zend_Search_Lucene_Storage_File {
/**
* Устанавливает индикатор позиции и перемещает указатель файла.
* Новая позиция, измеряемая в байтах от начала файла,
* получается добавлением смещения к позиции, определяемой аргументом $whence,
* который может принимать следующие значения:
* SEEK_SET - Устанавливает позицию равной смещению в байтах.
* SEEK_CUR - Устанавливает позицию равной текущей позиции плюс смещение.
* SEEK_END - Устанавливает позицию равной концу файла плюс смещение.
* (Для перемещения позиции относительно конца файла вы должны передать отрицательное значение смещения)
* В случае успеха возвращает 0; иначе -1
*
* @param integer $offset
* @param integer $whence
* @return integer
*/
public function seek($offset, $whence=SEEK_SET) {
...
}
/**
* Считывает $length байт из файла и перемещает указатель файла.
*
* @param integer $length
* @return string
*/
protected function _fread($length=1) {
...
}
}
?>