1 <sect1 id="zend.search.lucene.extending">
2 <title>Расширяемость<!--Extensibility--></title>
4 <sect2 id="zend.search.lucene.extending.analysis">
5 <title>Анализ текста<!--Text Analysis--></title>
7 Класс <code>Zend_Search_Lucene_Analysis_Analyzer</code> используется
8 индексатором для разбиения текстовых полей документа на лексемы.
10 <code>Zend_Search_Lucene_Analysis_Analyzer</code> class is used by indexer to tokenize document
17 <code>Zend_Search_Lucene_Analysis_Analyzer::getDefault()</code> и
18 <code>Zend_Search_Lucene_Analysis_Analyzer::setDefault()</code>
19 используются для получения и установки анализатора по умолчанию.
21 <code>Zend_Search_Lucene_Analysis_Analyzer::getDefault()</code> and <code>
22 Zend_Search_Lucene_Analysis_Analyzer::setDefault()</code> methods are used
23 to get and set default analyzer.
28 Таким образом, вы можете устанавливать собственный анализатор текста
29 или выбирать его из ряда предопределенных анализаторов:
30 <code>Zend_Search_Lucene_Analysis_Analyzer_Common_Text</code> и
31 <code>Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive</code>
32 (по умолчанию). Оба интерпретируют лексему как последовательность
33 букв. <code>Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive</code>
34 приводит лексемы к нижнему регистру.
36 Thus you can assign your own text analyzer or choose it from the set of predefined analyzers:
37 <code>Zend_Search_Lucene_Analysis_Analyzer_Common_Text</code> and
38 <code>Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive</code> (default).
39 Both of them interpret token as a sequence of letters.
40 <code>Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive</code>
41 converts tokens to lower case.
46 Переключение между анализаторами:
48 To switch between analyzers:
52 <programlisting language="php"><![CDATA[<?php
53 Zend_Search_Lucene_Analysis_Analyzer::setDefault(
54 new Zend_Search_Lucene_Analysis_Analyzer_Common_Text());
56 $index->addDocument($doc);]]></programlisting>
59 <code>Zend_Search_Lucene_Analysis_Analyzer_Common</code>
60 спроектирован для того, чтобы быть родительским классом для всех
61 анализаторов, определяемых пользователем. В наследующем классе
62 достаточно определить методы <code>reset()</code> и
63 <code>nextToken()</code>, которые берут строку из свойства $_input
64 и возвращают лексемы шаг за шагом (<constant>NULL</constant> означает конец
67 <code>Zend_Search_Lucene_Analysis_Analyzer_Common</code> is designed to be a parent for all user
68 defined analyzers. User should only define the <code>reset()</code> and <code>nextToken()</code> methods,
69 which take string from $_input member and returns tokens step by step
70 (<constant>NULL</constant> indicates end of stream).
75 Метод <code>nextToken()</code> должен использовать метод
76 <code>normalize()</code> для каждой лексемы. Это позволит
77 использовать фильтры лексем с вашим анализатором.
79 The <code>nextToken()</code> method should apply the <code>normalize()</code> method to each
80 token. It will allow you to use token filters with your analyzer.
85 Ниже приведен пример пользовательского анализатора, котрорый
86 принимает слова с цифрами как элементы:
88 Here is an example of a custom Analyzer, which takes words with digits as terms:
92 <title>Собственный анализатор текста<!--Custom text Analyzer.--></title>
93 <programlisting language="php"><![CDATA[<?php
94 /** Это созданный пользователем текстовый анализатор, который интерпретирует слова с цифрами как один элемент. */
96 /** Zend_Search_Lucene_Analysis_Analyzer hierarchy */
97 require_once 'Zend/Search/Lucene/Analysis/Analyzer.php';
99 class My_Analyzer extends Zend_Search_Lucene_Analysis_Analyzer_Common
104 * Установка позиции в начальное состояние
106 public function reset()
108 $this->_position = 0;
112 * API для разбиения на лексемы
113 * Получение следующей лексемы
114 * Возвращает null, если достигнут конец потока
116 * @return Zend_Search_Lucene_Analysis_Token|null
118 public function nextToken()
120 if ($this->_input === null) {
124 while ($this->_position < strlen($this->_input)) {
126 while ($this->_position < strlen($this->_input) &&
127 !ctype_alnum( $this->_input[$this->_position] )) {
131 $termStartPosition = $this->_position;
134 while ($this->_position < strlen($this->_input) &&
135 ctype_alnum( $this->_input[$this->_position] )) {
139 // Пустая лексема, конец потока
140 if ($this->_position == $termStartPosition) {
144 $token = new Zend_Search_Lucene_Analysis_Token(
145 substr($this->_input,
147 $this->_position - $termStartPosition),
150 $token = $this->normalize($token);
151 if ($token !== null) {
154 // Продолжение, если лексема пропущена
161 Zend_Search_Lucene_Analysis_Analyzer::setDefault(
162 new My_Analyzer());]]></programlisting>
167 <sect2 id="zend.search.lucene.extending.filters">
168 <title>Фильтрация лексем<!--Tokens Filtering--></title>
170 Анализатор <code>Zend_Search_Lucene_Analysis_Analyzer_Common</code>
171 также предоставляет механизм фильтрации лексем.
173 <code>Zend_Search_Lucene_Analysis_Analyzer_Common</code> analyzer also offers tokens filtering
179 Класс <code>Zend_Search_Lucene_Analysis_TokenFilter</code> является
180 уровнем абстракции для таких фильтров. Он должен использоваться как
181 предок для ваших собственных фильтров.
183 <code>Zend_Search_Lucene_Analysis_TokenFilter</code> class is an abstract level for such filters.
184 It should be used as an ancestor for your own filters.
189 Пользовательские фильтры должны реализовать метод
190 <code>normalize()</code>, который может преобразовывать лексему или
191 сигнализировать, что лексема должна быть пропущена.
193 Custom filter must implement <code>normalize()</code> method which may transform input token or signal that
194 token should be skipped.
199 В предоставляемом анализаторе уже определены три фильтра:
201 There are three filters already defined in Analysis subpackage:
206 <code>Zend_Search_Lucene_Analysis_TokenFilter_LowerCase</code>
208 <code>Zend_Search_Lucene_Analysis_TokenFilter_LowerCase</code> filter.
214 <code>Zend_Search_Lucene_Analysis_TokenFilter_ShortWords</code>
216 <code>Zend_Search_Lucene_Analysis_TokenFilter_ShortWords</code> filter.
222 <code>Zend_Search_Lucene_Analysis_TokenFilter_StopWords</code>
224 <code>Zend_Search_Lucene_Analysis_TokenFilter_StopWords</code> filter.
232 Фильтр <code>LowerCase</code> уже используется для анализатора
233 <code>Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive</code>,
234 который применяется по умолчанию.
236 <code>LowerCase</code> filter is already used for
237 <code>Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive</code> analyzer
243 <code>ShortWords</code> и <code>StopWords</code> могут
244 использоваться с уже включенными анализаторами или вашими
247 <code>ShortWords</code> and <code>StopWords</code> may be used with already defined or your own
252 <programlisting language="php"><![CDATA[<?php
253 $stopWords = array('a', 'an', 'at', 'the', 'and', 'or', 'is', 'am');
254 $stopWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_StopWords($stopWords);
256 $analyzer = new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive();
257 $analyzer->addFilter($stopWordsFilter);
259 Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer);]]></programlisting>
261 <programlisting language="php"><![CDATA[<?php
262 $shortWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_ShortWords();
264 $analyzer = new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive();
265 $analyzer->addFilter($shortWordsFilter);
267 Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer);]]></programlisting>
271 <code>Zend_Search_Lucene_Analysis_TokenFilter_StopWords</code>
272 принимает массив стоп-слов в качестве аргумента. Но стоп-слова можно
273 также загружать и из файла:
275 <code>Zend_Search_Lucene_Analysis_TokenFilter_StopWords</code> constructor takes an array of stop-words
276 as an input. But stop-words may be also loaded from a file:
280 <programlisting language="php"><![CDATA[<?php
281 $stopWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_StopWords();
282 $stopWordsFilter->loadFromFile($my_stopwords_file);
284 $analyzer = new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive();
285 $analyzer->addFilter($stopWordsFilter);
287 Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer);]]></programlisting>
290 Файл должен быть текстовым с одним словом в каждой строке. Символом
291 '#' помечаются строки с комментариями.
293 File should be a common text file with one word in each string. '#' marks string as a comment.
299 <code>Zend_Search_Lucene_Analysis_TokenFilter_ShortWords</code>
300 имеет один необязательный параметр, это ограничение длины слова.
301 Его значение по умолчанию равно 2.
303 <code>Zend_Search_Lucene_Analysis_TokenFilter_ShortWords</code> constructor has one optional argument.
304 It's a words length limit. Default value is 2.
310 <sect2 id="zend.search.lucene.extending.scoring">
311 <title>Алгоритмы ранжирования<!--Scoring Algorithms--></title>
313 Ранг <literal>q</literal> документа
314 <literal>d</literal> определяется следующим образом:
316 The score of query <literal>q</literal> for document <literal>d</literal>
317 is defined as follows:
322 <code>score(q,d) = sum( tf(t in d) * idf(t) * getBoost(t.field in d) * lengthNorm(t.field in d) ) *
323 coord(q,d) * queryNorm(q)</code>
327 tf(t in d) - <code>Zend_Search_Lucene_Search_Similarity::tf($freq)</code>
328 - коэффициент ранга, основанный на том, насколько часто встречается
329 элемент или фраза в документе.
331 tf(t in d) - <code>Zend_Search_Lucene_Search_Similarity::tf($freq)</code>
332 - a score factor based on a term or phrase's frequency in a document.
337 idf(t) - <code>Zend_Search_Lucene_Search_SimilaritySimilarity::tf($term, $reader)</code>
338 - коэффициент ранга для простого элемента применительно к определенному
341 idf(t) - <code>Zend_Search_Lucene_Search_SimilaritySimilarity::tf($term, $reader)</code>
342 - a score factor for a simple term for the specified index.
347 getBoost(t.field in d) - коэффициент усиления для поля элемента.
349 getBoost(t.field in d) - boost factor for the term field.
354 lengthNorm($term) - значение нормализации для поля, получаемое из
355 общего количества элементов, содержащихся в поле. Это значение
356 хранится внутри индекса. Эти значения вместе с коэффициентом усиления поля
357 хранятся в индексе, результатом их умножения является
358 ранг для каждого поля.
360 lengthNorm($term) - the normalization value for a field given the total
361 number of terms contained in a field. This value is stored within the index.
362 These values, together with field boosts, are stored in an index and multiplied
363 into scores for hits on each field by the search code.
367 Совпадения в длинных полях менее точны, поэтому реализации этого метода
368 обычно возвращают тем меньшие значения, чем
369 больше число лексем, и тем большие значения, чем меньше число лексем.
371 Matches in longer fields are less precise, so implementations of this method
372 usually return smaller values when numTokens is large, and larger values when numTokens is small.
377 сoord(q,d) - <code>Zend_Search_Lucene_Search_Similarity::coord($overlap, $maxOverlap)</code>
378 - коэффициент ранга, основанный на относительной доле всех элементов запроса,
379 найденных в документе.
381 coord(q,d) - <code>Zend_Search_Lucene_Search_Similarity::coord($overlap, $maxOverlap)</code> - a
382 score factor based on the fraction of all query terms that a document contains.
387 Присутствие большого количества элементов запроса означает лучшее
388 соответствие запросу, поэтому реализации этого метода обычно возвращают
389 бОльшие значения, когда соотношение между этими параметрами большое
390 и меньшие значения, когда соотношение между ними небольшое.
392 The presence of a large portion of the query terms indicates a better match
393 with the query, so implementations of this method usually return larger values
394 when the ratio between these parameters is large and smaller values when
395 the ratio between them is small.
400 queryNorm(q) - значение нормализации для запроса, получаемое из суммы
401 возведенных в квадрат весов каждого из элементов запроса. Это значение
402 затем умножается в вес каждого элемента запроса.
404 queryNorm(q) - the normalization value for a query given the sum of the squared weights
405 of each of the query terms. This value is then multiplied into the weight of each query
411 Это не влияет на ранжирование, цель нормализации состоит в том, чтобы
412 сделать соизмеримыми ранги, полученные при различных запросах.
414 This does not affect ranking, but rather just attempts to make scores from different
420 Алгоритм ранжирования может быть изменен через определение своего
421 собственного класса. Для этого надо создать потомка класса
422 Zend_Search_Lucene_Search_Similarity, как показано ниже, затем
424 <code>Zend_Search_Lucene_Search_Similarity::setDefault($similarity);</code>
425 для установки объекта как используемого по умолчанию.
427 Scoring algorithm can be customized by defining your own Similarity class. To do this
428 extend Zend_Search_Lucene_Search_Similarity class as defined below, then use
429 <code>Zend_Search_Lucene_Search_Similarity::setDefault($similarity);</code> method to set it as default.
433 <programlisting language="php"><![CDATA[<?php
435 class MySimilarity extends Zend_Search_Lucene_Search_Similarity {
436 public function lengthNorm($fieldName, $numTerms) {
437 return 1.0/sqrt($numTerms);
440 public function queryNorm($sumOfSquaredWeights) {
441 return 1.0/sqrt($sumOfSquaredWeights);
444 public function tf($freq) {
449 * Сейчас не используется. Подсчитывает сумму соответствий неточной фразе,
450 * основанную на изменяемом расстоянии.
452 public function sloppyFreq($distance) {
456 public function idfFreq($docFreq, $numDocs) {
457 return log($numDocs/(float)($docFreq+1)) + 1.0;
460 public function coord($overlap, $maxOverlap) {
461 return $overlap/(float)$maxOverlap;
465 $mySimilarity = new MySimilarity();
466 Zend_Search_Lucene_Search_Similarity::setDefault($mySimilarity);
468 ?>]]> </programlisting>
471 <sect2 id="zend.search.lucene.extending.storage">
472 <title>Контейнеры хранения<!--Storage Containers--></title>
474 Абстрактный класс <code>Zend_Search_Lucene_Storage_Directory</code>
475 определяет функционал директории.
477 An abstract class <code>Zend_Search_Lucene_Storage_Directory</code> defines
478 directory functionality.
483 Конструктор <code>Zend_Search_Lucene</code> использует строку или
484 объект <code>Zend_Search_Lucene_Storage_Directory</code> как входные данные.
486 The <code>Zend_Search_Lucene</code> constructor uses either a string or a
487 <code>Zend_Search_Lucene_Storage_Directory</code> object
493 <code>Zend_Search_Lucene_Storage_Directory_Filesystem</code> реализует
494 функционал директории для файловой системы.
496 <code>Zend_Search_Lucene_Storage_Directory_Filesystem</code> class implements directory
497 functionality for file system.
502 Если для конструктора <code>Zend_Search_Lucene</code> в качестве входных
503 данных испольуется строка, то считыватель индекса (объект
504 <code>Zend_Search_Lucene</code>) рассматривает ее как путь в файловой
505 системе и сама инстанцирует объекты
506 <code>Zend_Search_Lucene_Storage_Directory_Filesystem</code>.
508 If a string is used as an input for the <code>Zend_Search_Lucene</code> constructor, then the index
509 reader (<code>Zend_Search_Lucene</code> object) treats it as a file system path and instantiates
510 <code>Zend_Search_Lucene_Storage_Directory_Filesystem</code> objects by themselves.
515 Вы можете определить собственную реализацию директории,
516 создав потомка класса <code>Zend_Search_Lucene_Storage_Directory</code>.
518 You can define your own directory implementation by extending the
519 <code>Zend_Search_Lucene_Storage_Directory</code> class.
524 Методы <code>Zend_Search_Lucene_Storage_Directory</code>:
526 <code>Zend_Search_Lucene_Storage_Directory</code> methods:
530 <programlisting><![CDATA[<?php
532 abstract class Zend_Search_Lucene_Storage_Directory {
534 * Закрывает средство хранения.
538 abstract function close();
542 * Создает новый пустой файл с данным именем в директории.
544 * @param string $name
547 abstract function createFile($filename);
551 * Удаляет существующий файл в директории.
553 * @param string $filename
556 abstract function deleteFile($filename);
560 * Возвращает true, если файл с данным именем существует.
562 * @param string $filename
565 abstract function fileExists($filename);
569 * Возвращает длину файла в директории.
571 * @param string $filename
574 abstract function fileLength($filename);
578 * Возвращает время последнего изменения файла в формате UNIX.
580 * @param string $filename
583 abstract function fileModified($filename);
587 * Переименовывает существующий файл в директории.
589 * @param string $from
593 abstract function renameFile($from, $to);
597 * Устанавливает время изменения файла в текущее.
599 * @param string $filename
602 abstract function touchFile($filename);
606 * Возвращает объект Zend_Search_Lucene_Storage_File для данного файла в директории.
608 * @param string $filename
609 * @return Zend_Search_Lucene_Storage_File
611 abstract function getFileObject($filename);
615 ?>]]></programlisting>
618 Метод <code>getFileObject($filename)</code> класса
619 <code>Zend_Search_Lucene_Storage_Directory</code> возвращает
620 объект <code>Zend_Search_Lucene_Storage_File</code>.
622 <code>getFileObject($filename)</code> method of <code>Zend_Search_Lucene_Storage_Directory</code>
623 class returns a <code>Zend_Search_Lucene_Storage_File</code> object.
627 Абстрактный класс <code>Zend_Search_Lucene_Storage_File</code> реализует
628 абстракцию файла и примитивы чтения файла индекса.
630 <code>Zend_Search_Lucene_Storage_File</code> abstract class implements file abstraction and index
631 file reading primitives.
635 Вы должны создать класс, наследующий от <code>Zend_Search_Lucene_Storage_File</code>
636 для своей реализации директории.
638 You must also extend <code>Zend_Search_Lucene_Storage_File</code> for your Directory implementation.
642 Только два метода класса <code>Zend_Search_Lucene_Storage_File</code> должны быть
643 перегружены в вашей реализации:
645 Only two methods of <code>Zend_Search_Lucene_Storage_File</code> must be overloaded in your
650 <programlisting><![CDATA[<?php
652 class MyFile extends Zend_Search_Lucene_Storage_File {
654 * Устанавливает индикатор позиции и перемещает указатель файла.
655 * Новая позиция, измеряемая в байтах от начала файла,
656 * получается добавлением смещения к позиции, определяемой аргументом $whence,
657 * который может принимать следующие значения:
658 * SEEK_SET - Устанавливает позицию равной смещению в байтах.
659 * SEEK_CUR - Устанавливает позицию равной текущей позиции плюс смещение.
660 * SEEK_END - Устанавливает позицию равной концу файла плюс смещение.
661 * (Для перемещения позиции относительно конца файла вы должны передать отрицательное значение смещения)
662 * В случае успеха возвращает 0; иначе -1
664 * @param integer $offset
665 * @param integer $whence
668 public function seek($offset, $whence=SEEK_SET) {
673 * Считывает $length байт из файла и перемещает указатель файла.
675 * @param integer $length
678 protected function _fread($length=1) {
683 ?>]]></programlisting>