1 <?xml version="1.0" encoding="utf-8"?>
2 <!-- EN-Revision: 21829 -->
4 <sect1 id="zend.search.lucene.searching">
5 <title>Chercher dans un index</title>
6 <sect2 id="zend.search.lucene.searching.query_building">
7 <title>Construire des requêtes</title>
9 Il y a deux manières de chercher dans un index. La première
10 utilise le parseur de requête pour construire une requête à partir
11 d'une chaîne de caractères. La seconde consiste à créer vos
12 propres requêtes par programme à l'aide de l'<acronym>API</acronym>
13 <classname>Zend_Search_Lucene</classname>.
16 Avant de choisir d'utiliser le parseur de requête fourni, veuillez
17 considérer ce qui suit :
21 Si vous créez par programme une chaîne et qu'ensuite vous la passez dans
22 le parseur de requêtes, vous devriez considérer la possibilité
23 de construire vos requêtes directement avec l'<acronym>API</acronym> de
24 requêtes. En règle générale, le parseur est fait pour le texte saisi par
25 un utilisateur, pas pour du texte généré par programme.
30 Les champs non "tokenizés" devraient de préférences être ajoutés
31 directement aux requêtes et pas être passés dans le parseur. Si
32 les valeurs d'un champ sont générées par programme, les clauses de
33 requête pour ce champ devraient également être créées par programme.
34 Un analyseur, utilisé par le parseur de requêtes, est modélisé pour
35 convertir le texte saisi par l'utilisateur en des termes. Les valeurs
36 générées par programme, telles que dates, mot-clés, etc. devraient être
37 ajoutés avec l'<acronym>API</acronym> de requêtes.
42 Dans un formulaire de requête, les champs de texte général devraient
43 utiliser le parseur de requêtes. Tous les autres, tels qu'intervalles de
44 dates, mot-clés, etc., seront de préférence ajoutés directement dans
45 l'<acronym>API</acronym> de requêtes. Un champ avec une somme limitée de
46 valeurs qui peut être défini dans un menu déroulant ne devrait pas être
47 ajouté à une chaîne de requête qui serait ensuite parsée, mais devrait être
48 ajouté en tant que clause de type 'TermQuery'.
53 Les requêtes booléennes permettent au programmeur de combiner de manière
54 logique deux ou plus requêtes en une seule. De fait, c'est le meilleur
55 moyen d'ajouter des critères additionnels à une requête définie dans une
62 Les deux manières utilisent la même méthode d'<acronym>API</acronym> pour chercher
65 <programlisting language="php"><![CDATA[
66 $index = Zend_Search_Lucene::open('/data/my_index');
70 La méthode <methodname>Zend_Search_Lucene::find()</methodname> détermine automatiquement
71 le type de données entrantes et utilise le parseur de requêtes ou construit un objet
72 approprié à partir d''une donnée entrante de type chaîne de caractères.
75 Il est important de noter que le parseur de requêtes utilise l'analyseur standard
76 pour "tokenizer" les différentes partie d'une chaîne. Ainsi, toutes les transformations
77 qui sont appliquées aux textes indexés le sont également aux chaînes de requête.
80 L'analyseur standard peut transformer la chaîne de requête en minuscules pour
81 gérer l'insensibilité à la casse, retirer les mots exclus (ou "stop-words"), et
82 encapsuler les autres transformations.
85 La méthode de l'<acronym>API</acronym> ne transforme ni ne filtre les termes entrant
86 d'aucune façon. Elle est ainsi plus pratique pour les champs générés par le programme
87 ou ceux qui ne sont pas "tokenizés".
89 <sect3 id="zend.search.lucene.searching.query_building.parsing">
90 <title>Parsage de requêtes</title>
92 La méthode <methodname>Zend_Search_Lucene_Search_QueryParser::parse()</methodname>
93 peut être utilisée pour parser des chaînes de requête en objets de requête.
96 Cet objet de requête peut être utilisé dans une méthode de construction de requête de
97 l'<acronym>API</acronym> pour combiner des requêtes entrées par l'utilisateur avec
98 des requêtes générées par programme.
101 Pour l'instant, dans certains cas c'est le seul moyen de chercher des valeurs dans
102 des champs "non-tokenizés" :
103 Actually, in some cases it's the only way to search for values within untokenized
105 <programlisting language="php"><![CDATA[
106 $userQuery = Zend_Search_Lucene_Search_QueryParser::parse($queryStr);
107 $pathTerm = new Zend_Search_Lucene_Index_Term(
108 '/data/doc_dir/' . $filename, 'path'
110 $pathQuery = new Zend_Search_Lucene_Search_Query_Term($pathTerm);
111 $query = new Zend_Search_Lucene_Search_Query_Boolean();
112 $query->addSubquery($userQuery, true /* required */);
113 $query->addSubquery($pathQuery, true /* required */);
114 $hits = $index->find($query);
118 La méthode <methodname>Zend_Search_Lucene_Search_QueryParser::parse()</methodname>
119 prend également un paramètre optionnel d'encodage, qui permet de spécifier l'encodage
120 de la chaîne de requête :
121 <programlisting language="php"><![CDATA[
122 $userQuery = Zend_Search_Lucene_Search_QueryParser::parse($queryStr,
127 Si le paramètre d'encodage est omis, la locale courante est utilisée.
130 Il est également possible de spécifier l'encodage par défaut de la chaîne
131 de requête avec la méthode <methodname>Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding()</methodname> :
132 <programlisting language="php"><![CDATA[
133 Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('iso-8859-5');
135 $userQuery = Zend_Search_Lucene_Search_QueryParser::parse($queryStr);
139 <methodname>Zend_Search_Lucene_Search_QueryParser::getDefaultEncoding()</methodname>
140 retourne la valeur actuelle de l'encodage par défaut d'une chaîne de requête (une
141 chaîne vide signifiant "locale courante").
145 <sect2 id="zend.search.lucene.searching.results">
146 <title>Résultats de recherche</title>
148 Le résultat de recherche est un tableau d'objets
149 <classname>Zend_Search_Lucene_Search_QueryHit</classname>. Chacun d'eux a deux propriétés :
150 <code>$hit->id</code> est un identifiant numérique de document dans l'index et
151 <code>$hit->score</code> est le score du hit dans le résultat de recherche. Les résultats
152 sont triés par score (descendant depuis le meilleur score).
155 L'objet <classname>Zend_Search_Lucene_Search_QueryHit</classname> expose également
156 chaque champ du <classname>Zend_Search_Lucene_Document</classname> trouvé dans la
157 recherche en tant que propriété du hit. Dans l'exemple suivant, un hit est retourné avec
158 deux champs du document correspondant : title et author.
160 <programlisting language="php"><![CDATA[
161 $index = Zend_Search_Lucene::open('/data/my_index');
162 $hits = $index->find($query);
163 foreach ($hits as $hit) {
170 Les champs stockés sont toujours retournés encodés en UTF-8.
173 Optionnellement, l'objet original <classname>Zend_Search_Lucene_Document</classname>
174 peut être retourné depuis le <classname>Zend_Search_Lucene_Search_QueryHit</classname>.
175 Vous pouvez récupérer les parties stockées du document en utilisant la méthode
176 <methodname>getDocument()</methodname> de l'objet index, puis les obtenir avec la
177 méthode <methodname>getFieldValue()</methodname> :
179 <programlisting language="php"><![CDATA[
180 $index = Zend_Search_Lucene::open('/data/my_index');
181 $hits = $index->find($query);
182 foreach ($hits as $hit) {
183 // return Zend_Search_Lucene_Document object for this hit
184 echo $document = $hit->getDocument();
185 // return a Zend_Search_Lucene_Field object
186 // from the Zend_Search_Lucene_Document
187 echo $document->getField('title');
188 // return the string value of the Zend_Search_Lucene_Field object
189 echo $document->getFieldValue('title');
190 // same as getFieldValue()
191 echo $document->title;
195 Les champs disponibles dans l'objet <classname>Zend_Search_Lucene_Document</classname>
196 sont déterminés lors de l'indexation. Les champs sont soit indexés, soit indexés et stockés
197 dans le document par l'application d'indexage (p. ex. LuceneIndexCreation.jar).
200 Notez que l'identité du document ('path' dans notre exemple) est également
201 stocké dans l'index et doit être récupéré depuis l'index.
204 <sect2 id="zend.search.lucene.searching.results-limiting">
205 <title>Limiter le nombre de résultats</title>
207 L'opération la plus lourde au niveau du calcul dans une recherche est la calculation
208 des scores. Cela peut prendre plusieurs secondes pour un grand ensemble de résultats
209 (dizaine de milliers de hits).
212 <classname>Zend_Search_Lucene</classname> donne la possibilité de limiter la taille
213 de l'ensemble de résultats avec les méthodes <methodname>getResultSetLimit()</methodname>
214 et <methodname>setResultSetLimit()</methodname> :
215 <programlisting language="php"><![CDATA[
216 $currentResultSetLimit = Zend_Search_Lucene::getResultSetLimit();
217 Zend_Search_Lucene::setResultSetLimit($newLimit);
219 La valeur par défaut de 0 signifie 'pas de limite'.
222 Cela ne retournera pas les 'N meilleurs' résultats, mais seulement les 'N premiers'.
225 Les hits retournés demeurent triés par score ou par l'ordre spécifié, s'il est spécifié.
230 <sect2 id="zend.search.lucene.searching.results-scoring">
231 <title>Etablissement des scores des résultats de recherche</title>
233 <classname>Zend_Search_Lucene</classname> utilise le même algorithme de scoring que
234 Java Lucene. Par défaut, tous les hits dans l'ensemble de résultats sont triés par score.
235 Les hits avec le plus grand score viennent en premier, et les documents avec des hauts scores
236 devraient mieux correspondre à la requête que ceux avec des scores moins élevés.
239 En gros, les hits qui contiennent le terme ou la phrase cherché plus fréquemment
240 auront un score plus élevé.
243 Le score d'un hit peut être récupéré en accédant à la propriété <code>score</code> du hit :
245 <programlisting language="php"><![CDATA[
246 $hits = $index->find($query);
247 foreach ($hits as $hit) {
253 La classe <classname>Zend_Search_Lucene_Search_Similarity</classname> est utilisée
254 pour calculer le score pour chaque hit. Consultez la section <link
255 linkend="zend.search.lucene.extending.scoring">Extensibility. Scoring
256 Algorithms</link> pour des détails.
259 <sect2 id="zend.search.lucene.searching.sorting">
260 <title>Tri des résultats de recherche</title>
262 Par défaut, les résultats de recherche sont triés par score. Le programmeur peut
263 changer ce comportement en définissant des paramètres pour le champ de tri (ou une liste de champs), le
264 type de tri et le sens de tri.
267 L'appel à <code>$index->find()</code> peut prendre plusieurs paramètres optionnels :
268 <programlisting language="php"><![CDATA[
269 $index->find($query [, $sortField [, $sortType [, $sortOrder]]]
270 [, $sortField2 [, $sortType [, $sortOrder]]]
275 Le nom d'un champ stocké par lequel on veut trier les résultats devrait
276 être passé comme paramètre <varname>$sortField</varname>.
279 <varname>$sortType</varname> peut être omis ou prendre l'une des valeurs suivantes :
280 <constant>SORT_REGULAR</constant> (compare les éléments normalement- valeur par défaut),
281 <constant>SORT_NUMERIC</constant> (compare les éléments comme des valeurs numériques),
282 <constant>SORT_STRING</constant> (compare les éléments comme des chaînes de caractères).
285 <varname>$sortOrder</varname> peut être omis ou prendre l'une des valeurs suivantes :
286 <constant>SORT_ASC</constant> (trie dans l'ordre croissant- valeur par défaut),
287 <constant>SORT_DESC</constant> (trie dans l'ordre décroissant).
291 <programlisting language="php"><![CDATA[
292 $index->find($query, 'quantity', SORT_NUMERIC, SORT_DESC);
294 <programlisting language="php"><![CDATA[
295 $index->find($query, 'fname', SORT_STRING, 'lname', SORT_STRING);
297 <programlisting language="php"><![CDATA[
298 $index->find($query, 'name', SORT_STRING, 'quantity', SORT_NUMERIC, SORT_DESC);
302 Soyez prudents en personnalisant vos clés de tri; la requête aura besoin de récupérer
303 tous les documents correspondant de l'index, ce qui peut réduire considérablement les
304 performances de recherche.
307 <sect2 id="zend.search.lucene.searching.highlighting">
308 <title>Mise en évidence des résultats de recherche</title>
310 <classname>Zend_Search_Lucene</classname> propose deux options pour mettre en
311 évidence les résultats de recherche.
314 La première consiste à utiliser la classe <classname>Zend_Search_Lucene_Document_Html</classname>
315 (voyez <link linkend="zend.search.lucene.index-creation.html-documents">la section
316 Documents HTML</link> pour des détails) en utilisant les méthodes suivantes :
317 <programlisting language="php"><![CDATA[
319 * Mise en évidence de texte avec la couleur spécifiée
321 * @param string|array $words
322 * @param string $colour
325 public function highlight($words, $colour = '#66ffff');
327 <programlisting language="php"><![CDATA[
329 * Mise en évidence du texte en utilisant le View helper spécifié ou une
332 * @param string|array $words Les mots à mettre en évidence. Ils peuvent être organisés
333 dans un tableau ou une chaîne de caractères.
334 * @param callback $callback La méthode callback, utilisée pour transformer
335 (mettre en évidence) le texte.
336 * @param array $params Un tableau de paramètres additionnels passés à la fonction
337 callback (le premier paramètre non optionnel est un fragment
338 de code HTML pour la mise en évidence).
340 * @throws Zend_Search_Lucene_Exception
342 public function highlightExtended($words, $callback, $params = array())
346 Pour personnaliser le comportement de mise en évidence, utilisez la méthode
347 <methodname>highlightExtended()</methodname> avec le callback spécifié qui prendra
348 un ou plusieurs paramètres.
351 Le premier paramètre est un fragment de code HTML pour la mise en évidence et
352 les suivants sont dépendants du comportement du callback. La valeur de retour
353 est un fragment HTML mise en évidence.
356 , ou étendez la classe <classname>Zend_Search_Lucene_Document_Html</classname> et
357 redéfinissez la méthode <methodname>applyColour($stringToHighlight, $colour)</methodname>
358 qui est utilisée comme le callback de mise en évidence par défaut.
361 Dans les deux cas, le HTML retourné est automatiquement transformé en
362 <acronym>XHTML</acronym> valide.
367 Les <link linkend="zend.view.helpers">View helpers</link> peuvent également être utilisés
368 comme des callbacks dans un contexte d'affichage du script :
369 <programlisting language="php"><![CDATA[
370 $doc->highlightExtended('word1 word2 word3...', array($this, 'myViewHelper'));
374 Le résultat de l'opération de mise en évidence est récupéré avec
375 la méthode <code>Zend_Search_Lucene_Document_Html->getHTML()</code>.
379 La mise en évidence est exécutée dans les termes de l'analyseur courant. Donc toutes
380 les formes de mot(s) reconnues par l'analyseur seront mises en évidence.
383 Ex.: Si l'analyseur courant est insensible à la casse et que l'on demande à mettre
384 en évidence le mot 'text', alors 'text', 'Text', 'TEXT' ou toute autre combinaison de
385 casse seront mis en évidence.
388 Dans le même ordre d'idées, si l'analyseur courant supporte les requêtes proches (stemming)
389 et que l'on souhaite mettre en évidence 'indexed', alors 'index', 'indexing', 'indices' et
390 d'autres mots proches seront mis en évidences.
393 A l'inverse, si un mot est ignoré par l'analyseur courant (ex. si un filtre pour
394 ignorer les mots trop courts est appliqué à l'analyseur), alors rien ne sera mis en évidence.
398 La seconde option est d'utiliser la méthode
399 <code>Zend_Search_Lucene_Search_Query->highlightMatches(string $inputHTML[,
400 $defaultEncoding = 'UTF-8'[,
401 Zend_Search_Lucene_Search_Highlighter_Interface $highlighter]])</code>:
402 <programlisting language="php"><![CDATA[
403 $query = Zend_Search_Lucene_Search_QueryParser::parse($queryStr);
404 $highlightedHTML = $query->highlightMatches($sourceHTML);
408 Le second paramètre optionnel est l'encodage par défaut du document HTML. Il est
409 utilisé si l'encodage n'est pas spécifié dans le metatag HTTP-EQUIV Content-Type.
412 Le troisième paramètre optionnel est un objet de mise en évidence qui doit
413 implémenter l'interface <classname>Zend_Search_Lucene_Search_Highlighter_Interface</classname>:
414 <programlisting language="php"><![CDATA[
415 interface Zend_Search_Lucene_Search_Highlighter_Interface
418 * Définit le document pour la mise en évidence
420 * @param Zend_Search_Lucene_Document_Html $document
422 public function setDocument(Zend_Search_Lucene_Document_Html $document);
424 * Récupère le document pour la mise en évidence
426 * @return Zend_Search_Lucene_Document_Html $document
428 public function getDocument();
430 * Mise en évidence des mots spécifiés (appelée une fois par sous-requête)
432 * @param string|array $words Les mots à mettre en évidence. Ils peuvent être organisés
433 * dans un tableau ou une chaîne de caractères.
435 public function highlight($words);
438 Où l'objet <classname>Zend_Search_Lucene_Document_Html</classname> est un objet
439 construit à partir de la source HTML fournie par la méthode
440 <classname>Zend_Search_Lucene_Search_Query->highlightMatches()</classname>
443 Si le paramètre <varname>$highlighter</varname> est omis, un objet
444 <classname>Zend_Search_Lucene_Search_Highlighter_Default</classname> est
445 instancié et utilisé.
448 La méthode de mise en évidence <methodname>highlight()</methodname> est invoquée une
449 fois par sous-requête, ainsi elle a la possibilité de différencier la mise en évidence
453 La mise en évidence par défaut le fait en parcourant une table prédéfinie de couleurs.
454 Vous pouvez implémenter votre propre classe de mise en évidence ou juste étendre la classe
455 par défaut et redéfinir la table de couleurs.
458 <code>Zend_Search_Lucene_Search_Query->htmlFragmentHighlightMatches()</code> a un comportement
459 similaire. La seule différence est qu'il prend en entrée et retourne un fragment HTML sans
460 les balises <>HTML>, <HEAD>, <BODY>. Néanmoins, le fragment est automatiquement
461 transformé en <acronym>XHTML</acronym> valide.