La création et la mise à jour des index sont implémentées dans le composant
Zend_Search_Lucene
, ainsi que dans le projet Java Lucene. Vous
pouvez utiliser l'une ou l'autre de ces options pour créer des index dans lesquels
Zend_Search_Lucene
pourra chercher.
Le listing ci-dessous donne un exemple d'indexation d'un fichier en utilisant
l'API d'indexation de Zend_Search_Lucene
:
// Création de l'index $index = Zend_Search_Lucene::create('/data/my-index'); $doc = new Zend_Search_Lucene_Document(); // Stockage de l'URL du document afin de pouvoir l'identifier dans les résultats de recherche $doc->addField(Zend_Search_Lucene_Field::Text('url', $docUrl)); // Indexation des contenus du document $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $docContent)); // Ajout du document à l'index $index->addDocument($doc);
Les documents nouvellement ajoutés sont immédiatement recherchables dans l'index.
La même procédure est utilisée pour mettre à jour un index existant. La seule
différence est l'appel de la méthode open() à la place de create()
.
// Ouverture d'un index existant $index = Zend_Search_Lucene::open('/data/my-index'); $doc = new Zend_Search_Lucene_Document(); // Stockage de l'URL du document afin de pouvoir l'identifier dans les résultats de recherche $doc->addField(Zend_Search_Lucene_Field::Text('url', $docUrl)); // Indexation des contenus du document $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $docContent)); // Ajout du document à l'index $index->addDocument($doc);
Le format de fichier d'un index Lucene ne permet pas la mise à jour d'un document. Les documents doivent être supprimés puis réinsérés dans l'index afin d'être mis à jour efficacement.
La méthode Zend_Search_Lucene::delete()
utilise un
identifiant interne de document. Cet identifiant peut être récupéré dans une requête en
demandant la propriété 'id' :
$removePath = ...; $hits = $index->find('path:' . $removePath); foreach ($hits as $hit) { $index->delete($hit->id); }
Il existe deux méthodes pour récupérer la taille d'un index dans
Zend_Search_Lucene
.
La méthode Zend_Search_Lucene::maxDoc()
retourne un de plus
que le plus grand nombre possible de documents. Il s'agit en fait du nombre total de
documents dans l'index, y compris les documents supprimés. Cette méthode a une méthode
synonyme : Zend_Search_Lucene::count()
.
La méthode Zend_Search_Lucene::numDocs()
retourne le nombre
total de documents non supprimés.
$indexSize = $index->count(); $documents = $index->numDocs();
La méthode Zend_Search_Lucene::isDeleted($id)
peut être
utilisée pour vérifier si un document a été supprimé.
for ($count = 0; $count < $index->maxDoc(); $count++) { if ($index->isDeleted($count)) { echo "Le document #$id a été supprimé.\n"; } }
L'optimisation d'index retire les documents supprimés et resserre les identifiants de documents dans un intervalle plus petit. Ainsi, un identifiant interne de document peut être modifié durant l'optimisation de l'index.
Un index Lucene est composé de plusieurs segments. Chaque segment est un ensemble de données complètement indépendant des autres.
Les fichiers de segment d'index Lucene ne peuvent pas être mis à jour conceptuellement. Une mise à jour de segment requiert une réorganisation complète de tous les segments. Consultez les formats de fichiers d'index pour plus de détails (http://lucene.apache.org/java/2_3_0/fileformats.html) [11]Les nouveaux documents sont ajoutés à l'index en créant de nouveaux segments.
L'augmentation du nombre de segments réduit la qualité de l'index, mais l'optimisation de l'index remédie à ce problème. L'optimisation a pour principale activité de fusionner plusieurs segments en un seul. Ce processus ne met pas à jour les segments. Il génère un nouveau segment plus gros et met à jour la liste des segments ('segments' file).
L'optimisation complète de l'index peut être déclenchée en appelant la méthode
Zend_Search_Lucene::optimize()
. Elle va fusionner tous les
segments de l'index en un seul nouveau segment :
// Ouverture d'un index existant. $index = Zend_Search_Lucene::open('/data/my-index'); // Optimisation de l'index. $index->optimize();
L'optimisation automatique de l'index est lancée pour garder les index dans un état cohérent.
L'optimisation automatique est un processus itératif géré par plusieurs options d'index. Il s'agit de fusionner les très petits segments pour obtenir de plus gros segments, puis de fusionner ces segments obtenus vers des segments encore plus gros et ainsi de suite.
MaxBufferedDocs correspond au nombre minimum de documents requis avant que les documents présents en mémoire dans le buffer soit écris dans un nouveau segment.
MaxBufferedDocs peut être récupéré ou défini en appelant
$index->getMaxBufferedDocs()
ou
$index->setMaxBufferedDocs($maxBufferedDocs)
.
Sa valeur par défaut est 10.
MaxMergeDocs correspond à un nombre maximal de documents
fusionnés via addDocument()
. Des petites valeurs (p. ex., moins de
10'000) sont préférables pour de l'indexation interactive, du fait que cela limite
les pauses durant l'indexation à quelques secondes. Des valeurs plus grandes sont
meilleures pour les indexations en tâches planifiées (batch) et des recherches plus
rapides.
MaxMergeDocs peut être récupéré ou défini en appelant
$index->getMaxMergeDocs()
ou
$index->setMaxMergeDocs($maxMergeDocs)
.
Sa valeur par défaut est PHP_INT_MAX.
MergeFactor détermine à quelle fréquence les segments
d'index sont fusionnés par addDocument()
. Avec des petites valeurs, on
utilise moins de RAM durant l'indexation et les recherche sur des index non
optimisés sont plus rapides, mais la vitesse d'indexation est plus lente. Avec des
valeurs plus grandes, on utilise plus de RAM durant l'indexation, et tandis que les
recherches sur les index non optimisés sont plus lentes, l'indexation est plus
rapide. Au final, les grandes valeurs (> 10) sont préférables pour les
indexations planifiées (batch), et les valeurs plus petites (< 10) pour les index
qui sont maintenus de manière interactives.
L'option MergeFactor constitue une bonne estimation pour le nombre moyen de segments fusionnés par une passe d'auto-optimisation. Des valeurs trop grandes produisent un nombre trop important de segments car ils ne sont pas fusionnés. Cela peut causer l'erreur "failed to open stream: Too many open files". Cette limitation est dépendante du système.
MergeFactor peut être récupéré ou défini par les méthodes
$index->getMergeFactor()
ou
$index->setMergeFactor($mergeFactor)
.
Sa valeur par défaut est 10.
Lucene Java et Luke (Lucene Index Toolbox - http://www.getopt.org/luke/) peuvent aussi
être utilisés pour optimiser un index. La dernière version de Luke (v0.8) est basée
sur Lucene v2.3 et est compatible avec l'implémentation courante du composant
Zend_Search_Lucene
(ZF 1.6). Les versions précédentes de
Zend_Search_Lucene
nécessitent d'autres versions des outils
de Java Lucene :
-
ZF 1.5 - Java Lucene 2.1 (Luke tool v0.7.1 - http://www.getopt.org/luke/luke-0.7.1/)
-
ZF 1.0 - Java Lucene 1.4 - 2.1 (Luke tool v0.6 - http://www.getopt.org/luke/luke-0.6/)
Par défaut, les fichiers d'index sont disponibles en lecture et écriture par tout le monde.
Il est possible de surcharger ce comportement grâce à la méthode
Zend_Search_Lucene_Storage_Directory_Filesystem::setDefaultFilePermissions()
:
// Récupération des permissions par défaut $currentPermissions = Zend_Search_Lucene_Storage_Directory_Filesystem::getDefaultFilePermissions(); // Donne la permission lecture-écriture uniquement à l'utilisateur et au groupe courant. Zend_Search_Lucene_Storage_Directory_Filesystem::setDefaultFilePermissions(0660);
La taille de l'index est limité à 2GB sur les plate-formes 32 bits.
Utilisez des plate-formes 64 bits pour des index plus gros.
Zend_Search_Lucene
utilise flock()
pour
fournir des recherches concurrentes, la mise à jour des index et
l'optimisation.
Selon la documentation PHP,
"flock()
ne fonctionnera pas sur NFS et plusieurs autres systèmes de
fichiers en réseaux".
N'utilisez pas de systèmes de fichiers en réseaux avec
Zend_Search_Lucene
.
[11] Le format de fichier d'index supporté actuellement est la version 2.3 (depuis Zend Framework 1.6).