Zend_Search_Lucene-Searching.xml 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. <sect1 id="zend.search.lucene.searching">
  2. <title>Поиск по индексу<!--Searching an Index--></title>
  3. <sect2 id="zend.search.lucene.searching.query_building">
  4. <title>Построение запросов<!--Building Queries--></title>
  5. <para>
  6. Производить поиск по индексу можно двумя способами. Первый способ
  7. использует парсер запросов для построения запросов из строки.
  8. Второй способ дает возможность создавать свои запросы
  9. через программный интерфейс Zend_Search_Lucene.
  10. <!--
  11. There are two ways to search the index. The first method uses
  12. Query Parser to construct query from a string. The second provides
  13. the ability to create your own queries through the Zend_Search_Lucene API.
  14. -->
  15. </para>
  16. <para>
  17. В случае выбора парсера запросов учтите следующее:
  18. <!--
  19. Before choosing to use the provided Query Parser, please consider
  20. the following:
  21. -->
  22. <orderedlist>
  23. <listitem>
  24. <para>
  25. Если вы программно генерируете строку запроса и затем парсите
  26. ее с помощью парсера запросов, то вам следует серьезно подумать
  27. о построении запросов непосредственно через программный интерфейс.
  28. Другими словами, парсер запросов предназначен для текста, вводимого
  29. пользователем, а не генерируемого программным способом.
  30. <!--
  31. If you are programmatically generating a query string and then parsing
  32. it with the query parser then you should seriously consider building
  33. your queries directly with the query API. In other words, the query
  34. parser is designed for human-entered text, not for program-generated text.
  35. -->
  36. </para>
  37. </listitem>
  38. <listitem>
  39. <para>
  40. Не разбитые на лексемы поля лучше добавлять непосредственно
  41. в запросы, а не через парсер запросов. Если значения полей программно
  42. генерируются приложением, то должны быть отдельные элементы
  43. запроса для этого поля. Анализатор, используемый
  44. парсером запросов, предназначен для преобразования
  45. введенного пользователем текста в элементы запроса.
  46. Программно генерируемые значения, такие, как даты, ключевые слова
  47. и т.д., должны генерироваться единообразно.
  48. <!--
  49. Untokenized fields are best added directly to queries, and not through
  50. the query parser. If a field's values are generated programmatically
  51. by the application, then so should query clauses for this field.
  52. An analyzer, which the query parser uses, is designed to convert
  53. human-entered text to terms. Program-generated values, like dates,
  54. keywords, etc., should be consistently program-generated.
  55. -->
  56. </para>
  57. </listitem>
  58. <listitem>
  59. <para>
  60. В форме запроса поля с основным текстом должны использовать
  61. парсер запросов. Все остальные, такие, как периоды времени,
  62. ключевые слова и т.д, лучше добавлять непосредственно
  63. через программный интерфейс для запросов. Поля с ограниченным
  64. набором значений, которые могут отображаться в виде выпадающего
  65. списка, лучше не добавлять в строку запроса, которая
  66. парсится, а как элемент запроса.
  67. <!--
  68. In a query form, fields which are general text should use the query parser.
  69. All others, such as date ranges, keywords, etc. are better added directly
  70. through the query API. A field with a limit set of values, that can be
  71. specified with a pull-down menu should not be added to a query string
  72. which is subsequently parsed, but rather added as a TermQuery clause.
  73. -->
  74. </para>
  75. </listitem>
  76. <listitem>
  77. <para>
  78. Булевы запросы позволяют объединять несколько запросов в
  79. один. Таким образом, это является наилучшим путем
  80. добавления дополнительных критериев пользовательского
  81. поиска, определяемых строкой запроса.
  82. <!--
  83. Boolean queries allow to mix several other queries into new one.
  84. Thus it's the best way to add some additional criteria to user search, defined by
  85. a query string.
  86. -->
  87. </para>
  88. </listitem>
  89. </orderedlist>
  90. </para>
  91. <para>
  92. Оба способа используют один и тот же метод программного интерфейса
  93. для поиска в индексе:
  94. <!--
  95. Both ways use the same API method to search through the index:
  96. -->
  97. </para>
  98. <programlisting language="php"><![CDATA[<?php
  99. require_once('Zend/Search/Lucene.php');
  100. $index = Zend_Search_Lucene::open('/data/my_index');
  101. $index->find($query);]]> </programlisting>
  102. <para>
  103. Метод <code>Zend_Search_Lucene::find()</code> автоматически определяет
  104. тип ввода и использует парсер запросов для построения соответствующего
  105. объекта Zend_Search_Lucene_Search_Query.
  106. <!--
  107. The <code>Zend_Search_Lucene::find()</code> method determines input type automatically and
  108. uses query parser to construct appropriate Zend_Search_Lucene_Search_Query object
  109. from a string.
  110. -->
  111. </para>
  112. <para>
  113. Важно отметить, что парсер запросов использует стандартный
  114. анализатор для разбиения на лексемы отдельных частей строки запроса.
  115. Таким образом, все преобразования, проделываемые с индексируемым
  116. текстом, также проделываются и с частями строки запроса.
  117. <!--
  118. It is important to note that query parser uses standard analyzer to tokenize separate parts of query string.
  119. Thus all transformations, which are done on indexed text are also done on query string entries.
  120. -->
  121. </para>
  122. <para>
  123. Это могут быть приведение к нижнему регистру для того, чтобы сделать
  124. поиск нечувствительным к регистру, удаление запрещенных слов
  125. и т.д.
  126. <!--
  127. It may be transforming to lower case to make search case-insensitive, removing stop-words, stamming and
  128. mauch more other things.
  129. -->
  130. </para>
  131. <para>
  132. В противоположность парсеру запросов, методы API не преобразовывают
  133. или фильтруют входные элементы. Таким образом, API является более
  134. подходящим для сгенерированных компьютером или не разбитых на
  135. лексемы полей.
  136. <!--
  137. As opposed to it, API method doesn't transform or filter input terms. Thus it's more suitable for
  138. computer generated or untokenized fields.
  139. -->
  140. </para>
  141. <sect3 id="zend.search.lucene.searching.query_building.parsing">
  142. <title>Парсинг запроса<!--Query parsing--></title>
  143. <para>
  144. Метод <code>Zend_Search_Lucene_Search_QueryParser::parse()</code>
  145. может использоваться для парсинга строки запроса и
  146. преобразования ее в объект запроса.
  147. <!--
  148. <code>Zend_Search_Lucene_Search_QueryParser::parse()</code> method may be used to parse query string
  149. into query object.
  150. -->
  151. </para>
  152. <para>
  153. Этот объект может использоваться в методах программного
  154. интерфейса для объединения программно сгенерированных
  155. запросов с введенными пользователем.
  156. <!--
  157. This object may be used in query construction API methods to combine user entered queries with
  158. machine generated queries.
  159. -->
  160. </para>
  161. <para>
  162. Сейчас в некоторых случаях только таким способом можно будет
  163. производить поиск значений в полях, которые не были
  164. разбиты на лексемы.
  165. <!--
  166. Actually, in some cases it's only way to search for values within untokenized fields:
  167. -->
  168. <programlisting language="php"><![CDATA[<?php
  169. $userQuery = Zend_Search_Lucene_Search_QueryParser::parse($queryStr);
  170. $pathTerm = new Zend_Search_Lucene_Index_Term('/data/doc_dir/' . $filename, 'path');
  171. $pathQuery = new Zend_Search_Lucene_Search_Query_Term($pathTerm);
  172. $query = new Zend_Search_Lucene_Search_Query_Boolean();
  173. $query->addSubquery($userQuery, true /* required */);
  174. $query->addSubquery($pathQuery, true /* required */);
  175. $hits = $index->find($query);]]></programlisting>
  176. </para>
  177. <para>
  178. Метод <code>Zend_Search_Lucene_Search_QueryParser::parse()</code>
  179. также принимает необязательный параметр, через который
  180. указывается кодировка строки запроса.
  181. <!--
  182. <code>Zend_Search_Lucene_Search_QueryParser::parse()</code> method also takes optional encoding parameter,
  183. which can specify query string encoding:
  184. -->
  185. <programlisting language="php"><![CDATA[<?php
  186. $userQuery = Zend_Search_Lucene_Search_QueryParser::parse($queryStr, 'iso-8859-5');]]></programlisting>
  187. </para>
  188. <para>
  189. Если этот параметр опущен, то используется текущая локаль.
  190. <!--
  191. If encoding is omitted, then current locale is used.
  192. -->
  193. </para>
  194. <para>
  195. Можно также указать используемую по умолчанию кодировку для
  196. строки запроса через метод <code>Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding()</code>:
  197. <!--
  198. It's also possible to specify default query string encoding with
  199. <code>Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding()</code> method:
  200. -->
  201. <programlisting language="php"><![CDATA[<?php
  202. Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('iso-8859-5');
  203. ...
  204. $userQuery = Zend_Search_Lucene_Search_QueryParser::parse($queryStr);]]></programlisting>
  205. </para>
  206. <para>
  207. <code>Zend_Search_Lucene_Search_QueryParser::getDefaultEncoding()</code>
  208. возвращает используемую по умолчанию кодировку для строки
  209. запроса (пустая строка означает "текущая локаль").
  210. <!--
  211. <code>Zend_Search_Lucene_Search_QueryParser::getDefaultEncoding()</code> returns current default query
  212. string encoding (empty string means "current locale").
  213. -->
  214. </para>
  215. </sect3>
  216. </sect2>
  217. <sect2 id="zend.search.lucene.searching.results">
  218. <title>Результаты поиска<!--Search Results--></title>
  219. <para>
  220. Результат поиска является массивом объектов
  221. Zend_Search_Lucene_Search_QueryHit. Все эти объекты имеют два
  222. свойства: <varname>$hit->document</varname> - номер документа в индексе,
  223. <varname>$hit->score</varname> - ранг "хита" в результате поиска.
  224. Результат упорядочен по рангу ("хиты" с наибольшим рангом идут
  225. первыми).
  226. <!--
  227. The search result is an array of Zend_Search_Lucene_Search_QueryHit objects. Each of these has
  228. two properties: <varname>$hit->document</varname> is a document number within
  229. the index and <varname>$hit->score</varname> is a score of the hit in
  230. a search result. Result is ordered by score (top scores come first).
  231. -->
  232. </para>
  233. <para>
  234. Объект Zend_Search_Lucene_Search_QueryHit также предоставляют все
  235. поля документа Zend_Search_Lucene_Document как свойства объекта. В
  236. данном примере возвращается "хит" и соответствующий ему документ
  237. имеет два поля: заголовок и автор.
  238. <!--
  239. The Zend_Search_Lucene_Search_QueryHit object also exposes each field of the Zend_Search_Lucene_Document found by
  240. the hit as a property of the hit. In this example, a hit is returned and
  241. the corresponding document has two fields: title and author.
  242. -->
  243. </para>
  244. <programlisting language="php"><![CDATA[<?php
  245. require_once('Zend/Search/Lucene.php');
  246. $index = Zend_Search_Lucene::open('/data/my_index');
  247. $hits = $index->find($query);
  248. foreach ($hits as $hit) {
  249. echo $hit->score;
  250. echo $hit->title;
  251. echo $hit->author;
  252. }
  253. ?>]]></programlisting>
  254. <para>
  255. Сохраненные в индексе поля всегда возвращаются в кодировке UTF-8.
  256. <!--
  257. Stored fields are always returned in UTF-8 encoding.
  258. -->
  259. </para>
  260. <para>
  261. Исходный объект документа Zend_Search_Lucene_Document может также
  262. быть получен из Zend_Search_Lucene_Search_QueryHit. Вы можете
  263. извлечь сохраненные в индексе части документа, используя метод
  264. <code>getDocument()</code> объекта индекса и затем получая из через
  265. метод <code>getFieldValue()</code>:
  266. <!--
  267. Optionally, the original Zend_Search_Lucene_Document object can be returned from the
  268. Zend_Search_Lucene_Search_QueryHit.
  269. You can retrieve stored parts of the document by using the <code>getDocument()</code>
  270. method of the index object and then get them by
  271. <code>getFieldValue()</code> method:
  272. -->
  273. </para>
  274. <programlisting language="php"><![CDATA[<?php
  275. require_once('Zend/Search/Lucene.php');
  276. $index = Zend_Search_Lucene::open('/data/my_index');
  277. $hits = $index->find($query);
  278. foreach ($hits as $hit) {
  279. // возвращает объект для этого "хита"
  280. echo $document = $hit->getDocument();
  281. // возвращает объект Zend_Search_Lucene_Field
  282. // из Zend_Search_Lucene_Document
  283. echo $document->getField('title');
  284. // возвращает строковое значение объекта Zend_Search_Lucene_Field
  285. echo $document->getFieldValue('title');
  286. // делает то же самое, что и getFieldValue()
  287. echo $document->title;
  288. }
  289. ?>]]></programlisting>
  290. <para>
  291. Поля, доступные через объект Zend_Search_Lucene_Document, определяются
  292. во время индексирования. Поля документа либо только индексируются, либо
  293. индексируются и сохраняются в индексе индесирующим приложением
  294. (например, LuceneIndexCreation.jar).
  295. <!--
  296. The fields available from the Zend_Search_Lucene_Document object are determined at
  297. the time of indexing. The document fields are either indexed, or
  298. index and stored, in the document by the indexing application
  299. (e.g. LuceneIndexCreation.jar).
  300. -->
  301. </para>
  302. <para>
  303. Обратите внимание, что идентификатор документа (в нашем примере — 'path')
  304. также сохраняется в индексе и должен извлекаться из него.
  305. <!--
  306. Pay attention, that document identity ('path' in our example) is also stored
  307. in the index and must be retrieved from them.
  308. -->
  309. </para>
  310. </sect2>
  311. <sect2 id="zend.search.lucene.searching.results-scoring">
  312. <title>Ранжирование результата<!--Results Scoring--></title>
  313. <para>
  314. Zend_Search_Lucene использует тот же самый алгоритм ранжирования,
  315. что и Java Lucene. Результаты поиска по умолчанию сортируются по
  316. рангу (релевантности). "Хиты" с наибольшим рангом идут первыми, и
  317. документы, имеющие больший ранг, больше соответствуют запросу, чем
  318. документы с меньшим рангом.
  319. <!--
  320. Zend_Search_Lucene uses the same scoring algorithms as Java Lucene.
  321. Hits in search result are ordered by score by default. Hits with greater score come first, and
  322. documents having higher scores match the query more than documents having lower scores.
  323. -->
  324. </para>
  325. <para>
  326. Приблизительно говоря, документы, в которых искомый элемент или фраза
  327. встречаются чаще, будут иметь более высокий ранг.
  328. <!--
  329. Roughly speaking, search hits that contain the searched term or phrase more frequently
  330. will have a higher score.
  331. -->
  332. </para>
  333. <para>
  334. Число, соответствующее рангу, может быть получено через
  335. свойство <code>score</code>:
  336. <!--
  337. Score can be retrived by <code>score</code> property of hit:
  338. -->
  339. </para>
  340. <programlisting language="php"><![CDATA[<?php
  341. $hits = $index->find($query);
  342. foreach ($hits as $hit) {
  343. echo $hit->id;
  344. echo $hit->score;
  345. }]]> </programlisting>
  346. <para>
  347. Для вычисления ранга используется класс Zend_Search_Lucene_Search_Similarity.
  348. За подробностями см. раздел
  349. <link linkend="zend.search.lucene.extending.scoring">Расширяемость. Алгоритмы ранжирования</link>.
  350. <!--
  351. Zend_Search_Lucene_Search_Similarity class is used to calculate score.
  352. See <link linkend="zend.search.lucene.extending.scoring">Extensibility. Scoring Algorithms</link> section for details.
  353. -->
  354. </para>
  355. </sect2>
  356. <sect2 id="zend.search.lucene.searching.sorting">
  357. <title>Сортировка результатов поиска<!--Search Result Sorting--></title>
  358. <para>
  359. По умолчанию результаты поиска сортируются по рангу. Вы можете
  360. изменить это поведение установкой поля (полей) для сортировки, типа
  361. сортировки и порядка сортировки.
  362. <!--
  363. Search result is sorted by score by default. You change this by setting a sort field (or fields), sort type
  364. and sort order parameters.
  365. -->
  366. </para>
  367. <para>
  368. <varname>$index->find()</varname> может принимать несколько необязательных
  369. параметров:
  370. <!--
  371. <varname>$index->find()</varname> call may take several optional parameters:
  372. -->
  373. <programlisting language="php"><![CDATA[<?php
  374. $index->find($query [, $sortField [, $sortType [, $sortOrder]]] [, $sortField2 [, $sortType [, $sortOrder]]] ...);]]></programlisting>
  375. </para>
  376. <para>
  377. <varname>$sortField</varname> является именем сохраненного в индексе поля
  378. для сортировки результата.
  379. <!--
  380. <varname>$sortField</varname> is a name of stored field to sort result.
  381. -->
  382. </para>
  383. <para>
  384. <varname>$sortType</varname> может быть опущен или принимать значения
  385. <code>SORT_REGULAR</code> (сравнивать элементы как обычно, значение по умолчанию),
  386. <code>SORT_NUMERIC</code> (сравнивать элементы как числа),
  387. <code>SORT_STRING</code> (сравнивать элементы как строки).
  388. <!--
  389. <varname>$sortType</varname> may be omitted or take values
  390. <code>SORT_REGULAR</code> (compare items normally, default value),
  391. <code>SORT_NUMERIC</code> (compare items numerically),
  392. <code>SORT_STRING</code> (compare items as strings).
  393. -->
  394. </para>
  395. <para>
  396. <varname>$sortOrder</varname> может быть опущен или принимать значения
  397. <code>SORT_ASC</code> (сортировать в порядке возрастания, значение по умолчанию),
  398. <code>SORT_DESC</code> (сортировать в порядке убывания).
  399. <!--
  400. <varname>$sortOrder</varname> may be omitted or take values
  401. <code>SORT_ASC</code> (sort in ascending order, default value),
  402. <code>SORT_DESC</code> (sort in descending order).
  403. -->
  404. </para>
  405. <para>
  406. <!--
  407. Examples:
  408. -->
  409. <programlisting language="php"><![CDATA[<?php
  410. $index->find($query, 'quantity', SORT_NUMERIC, SORT_DESC);]]></programlisting>
  411. <programlisting language="php"><![CDATA[<?php
  412. $index->find($query, 'fname', SORT_STRING, 'lname', SORT_STRING);]]></programlisting>
  413. <programlisting language="php"><![CDATA[<?php
  414. $index->find($query, 'name', SORT_STRING, 'quantity', SORT_NUMERIC, SORT_DESC);]]></programlisting>
  415. </para>
  416. <para>
  417. Будьте осторожны, когда используете сортировку, отличную от
  418. принятой по умолчанию. Для этого нужно полное извлечение документов
  419. из индекса, что может привести к резкому снижению
  420. производительности.
  421. <!--
  422. Please be careful when using non-default search order.
  423. It needs to retrive documents completely from an index and may drammatically slow down search performance.
  424. -->
  425. </para>
  426. </sect2>
  427. <sect2 id="zend.search.lucene.searching.highlighting">
  428. <title>Подсветка результатов поиска<!--Search Results Highlighting--></title>
  429. <para>
  430. Метод
  431. <code>Zend_Search_Lucene_Search_Query::highlightMatches()</code>
  432. позволяет подсвечивать в HTML-документе элементы, присутствующие в
  433. контексте поискового запроса:
  434. <!--
  435. <code>Zend_Search_Lucene_Search_Query::highlightMatches()</code>
  436. method allows to highlight HTML document terms
  437. in context of search query:
  438. -->
  439. <programlisting language="php"><![CDATA[<?php
  440. $query = Zend_Search_Lucene_Search_QueryParser::parse($queryStr);
  441. $hits = $index->find($query);
  442. ...
  443. $highlightedHTML = $query->highlightMatches($sourceHTML);]]></programlisting>
  444. </para>
  445. <para>
  446. Метод <code>highlightMatches()</code> для обработки HTML использует
  447. класс <code>Zend_Search_Lucene_Document_Html</code> (см.
  448. <link linkend="zend.search.lucene.index-creation.html-documents">раздел
  449. "HTML-документы"</link>). Поэтому этот метод предъявляет те же
  450. требования к HTML-коду, что и используемый класс.
  451. <!--
  452. <code>highlightMatches()</code> method utilizes
  453. <code>Zend_Search_Lucene_Document_Html</code> class
  454. (see <link linkend="zend.search.lucene.index-creation.html-documents">HTML
  455. documents section</link> for details)
  456. for HTML processing. So it has the same requirements for HTML source.
  457. -->
  458. </para>
  459. </sect2>
  460. </sect1>
  461. <!--
  462. vim:se ts=4 sw=4 et:
  463. -->