| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485 |
- <?xml version="1.0" encoding="utf-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.search.lucene.extending">
- <title>Extensibilité</title>
- <sect2 id="zend.search.lucene.extending.analysis">
- <title>Analyse de texte</title>
- <para>
- La classe <classname>Zend_Search_Lucene_Analysis_Analyzer</classname> est utilisé par
- l'indexeur afin de transformer en segments les champs texte du document.
- </para>
- <para>
- Les méthodes <methodname>Zend_Search_Lucene_Analysis_Analyzer::getDefault()</methodname>
- et <code>Zend_Search_Lucene_Analysis_Analyzer::setDefault()</code> sont utilisées pour
- récupérer et définir l'analyseur par défaut.
- </para>
- <para>
- Vous pouvez assigner votre propre analyseur de texte ou choisir parmi un ensemble
- d'analyseurs prédéfinis :
- <classname>Zend_Search_Lucene_Analysis_Analyzer_Common_Text</classname> et
- <classname>Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive</classname>
- (par défaut). Tout deux interprètent les segments comme des séquences de lettres.
- <classname>Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive</classname>
- convertit tous les segments en minuscule.
- </para>
- <para>
- Pour changer d'analyseur :
- </para>
- <programlisting language="php"><![CDATA[
- Zend_Search_Lucene_Analysis_Analyzer::setDefault(
- new Zend_Search_Lucene_Analysis_Analyzer_Common_Text());
- ...
- $index->addDocument($doc);
- ]]></programlisting>
- <para>
- La classe <classname>Zend_Search_Lucene_Analysis_Analyzer_Common</classname> a été conçu
- pour être l'ancêtre de tous les analyseurs définis par l'utilisateur. L'utilisateur doit
- uniquement définir les méthodes <methodname>reset()</methodname> et
- <methodname>nextToken()</methodname>, qui prennent leur chaîne de caractères depuis la
- propriété $_input et retournent les segments un par un (une valeur
- <constant>NULL</constant> indique la fin du flux).
- </para>
- <para>
- La méthode <methodname>nextToken()</methodname> doit appeler la méthode
- <methodname>normalize()</methodname> sur chacun des segments. Ce qui vous permet
- d'utiliser des filtres de segments avec votre analyseur.
- </para>
- <para>
- Voici l'exemple d'analyseur personnalisé, qui accepte des mots contenant des chiffres
- comme terme :
- <example id="zend.search.lucene.extending.analysis.example-1">
- <title>Analyseur de texte personnalisé</title>
- <programlisting language="php"><![CDATA[
- /**
- * Voici un analyseur de texte qui traite les mots contenant des chiffres comme
- * un seul terme
- */
- class My_Analyzer extends Zend_Search_Lucene_Analysis_Analyzer_Common
- {
- private $_position;
- /**
- * Remet à Zéro le flux de segments
- */
- public function reset()
- {
- $this->_position = 0;
- }
- /**
- * API du flux de segmentation
- * Récupère le segment suivant
- * Retourne null à la fin du flux
- *
- * @return Zend_Search_Lucene_Analysis_Token|null
- */
- public function nextToken()
- {
- if ($this->_input === null) {
- return null;
- }
- while ($this->_position < strlen($this->_input)) {
- // Saute les espaces
- while ($this->_position < strlen($this->_input) &&
- !ctype_alnum( $this->_input[$this->_position] )) {
- $this->_position++;
- }
- $termStartPosition = $this->_position;
- // lit le segment
- while ($this->_position < strlen($this->_input) &&
- ctype_alnum( $this->_input[$this->_position] )) {
- $this->_position++;
- }
- // Segment vide, fin de flux.
- if ($this->_position == $termStartPosition) {
- return null;
- }
- $token = new Zend_Search_Lucene_Analysis_Token(
- substr($this->_input,
- $termStartPosition,
- $this->_position -
- $termStartPosition),
- $termStartPosition,
- $this->_position);
- $token = $this->normalize($token);
- if ($token !== null) {
- return $token;
- }
- // Continue si le segment est sauté
- }
- return null;
- }
- }
- Zend_Search_Lucene_Analysis_Analyzer::setDefault(
- new My_Analyzer());
- ]]></programlisting>
- </example>
- </para>
- </sect2>
- <sect2 id="zend.search.lucene.extending.filters">
- <title>Filtrage des segments</title>
- <para>
- L'analyseur <classname>Zend_Search_Lucene_Analysis_Analyzer_Common</classname> offre
- aussi un mécanisme de filtrage des segments.
- </para>
- <para>
- La classe <classname>Zend_Search_Lucene_Analysis_TokenFilter</classname> fournit une
- interface abstraites pour ces filtres.
- Vos propres filtres devraient étendre cette classe directement ou indirectement.
- </para>
- <para>
- Chaque filtre personnalisé doit implémenter la méthode
- <methodname>normalize()</methodname> qui devrait transformer le segment en entrée ou
- signaler que le segment courant doit être sauté.
- </para>
- <para>
- Il y a trois filtres déjà défini dans le sous-paquet d'analyse :
- <itemizedlist>
- <listitem>
- <para>
- <classname>Zend_Search_Lucene_Analysis_TokenFilter_LowerCase</classname>
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Search_Lucene_Analysis_TokenFilter_ShortWords</classname>
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Search_Lucene_Analysis_TokenFilter_StopWords</classname>
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- Le filtre <code>LowerCase</code> filtre est déjà utilisé par défaut par l'analyseur
- <classname>Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive</classname>.
- </para>
- <para>
- Les filtres <code>ShortWords</code> et <code>StopWords</code> peuvent être utilisés avec
- des analyseurs prédéfinis ou personnalisés comme ceci :
- <programlisting language="php"><![CDATA[
- $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);
- ]]></programlisting>
- <programlisting language="php"><![CDATA[
- $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);
- ]]></programlisting>
- </para>
- <para>
- Le constructeur <classname>Zend_Search_Lucene_Analysis_TokenFilter_StopWords</classname>
- prends un tableau de stop-words en entrée.
- Mais les stop-words peuvent aussi être chargé à partir d'un fichier :
- <programlisting language="php"><![CDATA[
- $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);
- ]]></programlisting>
- Ce fichier doit être un simple fichier texte avec un mot par ligne. Le caractère '#'
- transforme la ligne en commentaire.
- </para>
- <para>
- Le constructeur de la classe
- <classname>Zend_Search_Lucene_Analysis_TokenFilter_ShortWords</classname> a un argument
- optionnel.
- Il s'agit de la longueur maximum de mot, elle est définie par défaut à 2.
- </para>
- </sect2>
- <sect2 id="zend.search.lucene.extending.scoring">
- <title>Algorithme de score</title>
- <para>
- Le score d'un document <literal>d</literal> pour une requête <literal>q</literal>
- est défini comme suit :
- </para>
- <para>
- <code>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)</code>
- </para>
- <para>
- tf(t in d) - <methodname>Zend_Search_Lucene_Search_Similarity::tf($freq)</methodname> -
- un facteur de score basé sur la fréquence d'un terme ou d'une phrase dans un document.
- </para>
- <para>
- idf(t) -
- <methodname>Zend_Search_Lucene_Search_Similarity::idf($input, $reader)</methodname> -
- un facteur de score pour un terme simple de l'index spécifié.
- </para>
- <para>
- getBoost(t.field in d) - le facteur d'impulsion pour le champ du terme.
- </para>
- <para>
- lengthNorm($term) - la valeur de normalisation pour un champ donné du nombre total de
- terme contenu dans un champ. Cette valeur est stockée dans l'index.
- Ces valeurs, ainsi que celle du champ d'impulsion, sont stocké dans un index et
- multipliées par le score de hits par code de recherche sur chaque champ.
- </para>
- <para>
- La correspondance au sein de champs plus long est moins précise, ainsi l'implémentation
- de cette méthode retourne généralement de plus petites valeurs quand numTokens est
- important, et de plus grandes valeurs lorsque numTokens est petit.
- </para>
- <para>
- coord(q,d) -
- <methodname>
- Zend_Search_Lucene_Search_Similarity::coord($overlap, $maxOverlap)
- </methodname> - un facteur de score basé sur la fraction de tout les termes de la
- recherche que le document contient.
- </para>
- <para>
- La présence d'une grande partie des termes de la requête indique une meilleure
- correspondance avec la requête, ainsi les implémentations de cette méthode retourne
- habituellement de plus grandes valeurs lorsque le ration entre ces paramètres est grand
- que lorsque le ratio entre elle est petit.
- </para>
- <para>
- queryNorm(q) - la valeur de normalisation pour la requête en fonction de la somme des
- poids au carré de chaque terme de la requête.
- Cette valeur est ensuite multipliée par le poids de chacun des termes de la requête.
- </para>
- <para>
- Ceci n'affecte pas le classement, mais tente plutôt de faire des scores à partir de
- différentes requêtes comparables entre elles.
- </para>
- <para>
- Les algorithmes de score peuvent être personnalisés en définissant votre propre classe
- de similitude.
- Pour ce faire, étendez la classe
- <classname>Zend_Search_Lucene_Search_Similarity</classname> comme défini ci-dessous,
- puis appelez la méthode
- <classname>Zend_Search_Lucene_Search_Similarity::setDefault($similarity);</classname>
- afin de la définir par défaut.
- </para>
- <programlisting language="php"><![CDATA[
- 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) {
- return sqrt($freq);
- }
- /**
- * Ceci n'est pas encore utilisé. Cela évalue le nombre de correspondance
- * d'expressions vagues, basé sur une distance d'édition.
- */
- 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);
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.search.lucene.extending.storage">
- <title>Conteneur de stockage</title>
- <para>
- La classe abstraite <classname>Zend_Search_Lucene_Storage_Directory</classname> définit
- la fonctionnalité de répertoire.
- </para>
- <para>
- Le constructeur <classname>Zend_Search_Lucene</classname> utilise soit une chaîne soit
- un objet <classname>Zend_Search_Lucene_Storage_Directory</classname> en paramètre.
- </para>
- <para>
- La classe <classname>Zend_Search_Lucene_Storage_Directory_Filesystem</classname>
- implémente la fonctionnalité de répertoire pour un système de fichier.
- </para>
- <para>
- Si une chaîne est utilisé comme paramètre du constructeur
- <classname>Zend_Search_Lucene</classname>, le lecteur
- (<classname>Zend_Search_Lucene</classname> object) le considère comme un chemin dans le
- système de fichier et instancie l'objet
- <classname>Zend_Search_Lucene_Storage_Directory_Filesystem</classname>.
- </para>
- <para>
- Vous pouvez définir votre propre implémentation de répertoire en étendant la classe
- <classname>Zend_Search_Lucene_Storage_Directory</classname>.
- </para>
- <para>
- Les méthodes de<classname>Zend_Search_Lucene_Storage_Directory</classname> :
- </para>
- <programlisting language="php"><![CDATA[
- abstract class Zend_Search_Lucene_Storage_Directory {
- /**
- * Ferme le stockage.
- *
- * @return void
- */
- abstract function close();
- /**
- * Crée un nouveau fichier vide dans le répertoire dont le nom est $filename.
- *
- * @param string $name
- * @return void
- */
- abstract function createFile($filename);
- /**
- * Supprime un fichier existant du répertoire.
- *
- * @param string $filename
- * @return void
- */
- abstract function deleteFile($filename);
- /**
- * Retourne true si un fichier portant le nom donné existe.
- *
- * @param string $filename
- * @return boolean
- */
- abstract function fileExists($filename);
- /**
- * Retourne la taille d'un $filename dans le répertoire.
- *
- * @param string $filename
- * @return integer
- */
- abstract function fileLength($filename);
- /**
- * Retourne le timestamp UNIX de la date de modification de $filename.
- *
- * @param string $filename
- * @return integer
- */
- abstract function fileModified($filename);
- /**
- * Renomme un fichier existant dans le répertoire.
- *
- * @param string $from
- * @param string $to
- * @return void
- */
- abstract function renameFile($from, $to);
- /**
- * Définit la date de modification de $filename à la date de maintenant.
- *
- * @param string $filename
- * @return void
- */
- abstract function touchFile($filename);
- /**
- * Retourne un objet Zend_Search_Lucene_Storage_File object pour un $filename
- * donné dans le répertoire
- *
- * @param string $filename
- * @return Zend_Search_Lucene_Storage_File
- */
- abstract function getFileObject($filename);
- }
- ]]></programlisting>
- <para>
- La méthode <methodname>getFileObject($filename)</methodname> de l'instance
- <classname>Zend_Search_Lucene_Storage_Directory</classname> retourne un objet
- <classname>Zend_Search_Lucene_Storage_File</classname>.
- </para>
- <para>
- La classe abstraite <classname>Zend_Search_Lucene_Storage_File</classname> implémente
- l'abstraction de fichiers et les primitives de lecture de fichier d'index.
- </para>
- <para>
- Vous devez aussi étendre <classname>Zend_Search_Lucene_Storage_File</classname> dans
- votre implémentation de répertoire.
- </para>
- <para>
- Seulement deux méthodes de <classname>Zend_Search_Lucene_Storage_File</classname>
- doivent être surchargées dans votre implémentation :
- </para>
- <programlisting language="php"><![CDATA[
- class MyFile extends Zend_Search_Lucene_Storage_File {
- /**
- * Définit l'indicateur de position du fichier and avance le pointeur
- * de fichier.
- * La nouvelle position, calculé en octets depuis le début du fichier,
- * est obtenu en ajoutant l'offset à la position spécifiée par $whence,
- * dont les valeurs sont définit comme suit :
- * SEEK_SET - Définit la position comme égale aux octets de l'offset.
- * SEEK_CUR - Définit la position à la position courante plus l'offset.
- * SEEK_END - Définit la position à la fin du fichier plus l'offset.
- *(Pour déplacer à une position avant la fin du fichier, vous devrez passer
- * une valeur négative à l'offset.)
- * En cas de succès, retourne 0; sinon, retourne -1
- *
- * @param integer $offset
- * @param integer $whence
- * @return integer
- */
- public function seek($offset, $whence=SEEK_SET) {
- ...
- }
- /**
- * Lit $length octets dans le fichier et avance le pointeur de fichier.
- *
- * @param integer $length
- * @return string
- */
- protected function _fread($length=1) {
- ...
- }
- }
- ]]></programlisting>
- </sect2>
- </sect1>
|