Solr : configuration

Implémenter Solr dans une application web Java

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com
En tant qu'un "serveur", Solr bénéficie des mêmes droits que des serveurs normaux, comme Apache. Avant toute chose, il faut donc s'occuper de la configuration, qui fera sujet de l'article ci-dessous.

Dans cet article on va aborder la configuration du Solr. A travers elle, on verra les concepts fondamentaux du système. On présentera, entre autres, request handler (gestionnaire des requêtes), analyzers (analysateurs), filtres et écrivain de réponse (query response writer). On verra tout cela à travers le fichier de configuration utilisé qui sera affiché bout à bout, aspect par aspect. Chaque bout de code sera accompagné d'une note explicative. A la fin de l'article vous trouverez le fichier de configuration complet et exploitable.

Toute la configuration est englobée avec la balise <config />, dont les enfants directs sont :


  1. <luceneMatchVersion />
    La version de Lucene pour laquelle fonctionnent les éléments Solr.


  2. <lib />
    Ce tag indique le répertoire dans lequel doit piocher Solr pour récupérer les JAR des classes utilisées.


  3. <directoryFactory />
    La fabrique qui permet de manipuler les repértoires ou les endroits dans la mémoire (pour RAMDirectoryFactory).


  4. <codecFactory />
    Ici on définit le format de l'indexe inversé. Son implémentation par défaut est SchemaCodecFactory qui, en même temps, est le format standard de Lucene.


  5. <schemaFactory />
    Cette "fabrique de schéma" permet de déterminer la façon de lire le fichier contenant le schéma des indexes. Le fichier XML par défaut s'appelle schema.xml et c'est lui qu'on utilisera dans nos exemples. Cependant, il existe un moyen de personnaliser cette configuration, avec la classe ManagedIndexSchemaFactory. Dans ce cas, elle doit être accompagnée d'une balise <str name="managedSchemaResourceName" /> qui contiendra le nom du nouveau schéma. Un autre enfant de cette balise, <bool name="mutable" />, indique si l'on peut modifier le fichier depuis l'extérieur, via un web service.



  6. <indexConfig />
    La famille de ce paramètre permet de contrôler l'indexation au très bas niveau d'indexation.


    • <maxIndexingThreads />
      Le nombre maximal des threads qui peuvent indexer les éléments.


    • <lockType />
      Il détermine la stratégie à adapter pour l'écriture concurrentielle de l'index. Dans notre application on utilisera le vérouillage natif (NativeFSLockFactory. Il implémente le vérouillage du système d'exploitation sur lequel est installé Solr.


    • <unlockOnStartup />
      Cette balise spécifie si au démarrage, Solr doit devérouiller tous les vérouillages d'écriture en cours. L'option par défaut est false et c'est cette valeur qu'on utilisera dans notre exemple.




  7. <updateHandler />
    Il précise la façon d'ajouter les éléments dans Solr.


    • <updateLog />
      L'emplacement des logs pour les transactions.


    • <autoCommit />
      Il contient la configuration pour l'auto-sauvegarde des données. L'opération peut ne pas être totalement terminée, mais à travers les données de cette configuration, une partie de l'opération sera sauvegardé dans Solr.


      • <maxTime />
        Le lapsus de temps (en milisecondes) qui doit passer avant que les éléments soient indexés.


      • <openSearcher />
        Si faux, les éléments qui seront rajoutés dans l'index. Cependant, cet ajout ne provoquera pas l'ouverture d'une nouvelle recherche qui les rendra visible publiquement.






  8. <query />
    Les éléments de cette balise permettent de contrôler le cache.


    • <filterCache />
      Il permet de configurer le cache pour des groupes des documents indexés, mais non-ordonnés, correspondant aux critères de la requête.


    • <queryResultCache />
      Ici on peut configurer le cache pour les résultats finaux d'une requête.


    • <documentCache />
      Le cache qui stocke les objets Document de Lucene (champs de chaque document).




  9. <requestDispatcher />
    Le tag qui détermine le comportement de Solr pour les requêtes contenant /select. Si l'attribut handleSelect est faux, Solr va ignorer toutes ces requêtes. L'exception à la règle font des requêtes contenant le gestionnaire défini explicitement dans leurs paramètres.


    • <requestParsers />
      La configuration pour le parseur de la requête. Son attribut enableRemoteStreaming indique si l'on accepte les données issues d'un stream. multipartUploadLimitInKB détermine la taille maximale du fichier envoyé via une requête, tandis que formdataUploadLimitInKB spécifie la taille maximale d'un formulaire (type application/x-www-form-urlencoded) envoyé au Solr. En ce qui concerne l'inclusion des paramètres de la requête au SolrQueryRequest, c'est l'attribut addHttpRequestToContext qui peut le faire.


    • <httpCaching />
      Cette balise précise le cache HTTP que doit implémenter Solr. A la base, Solr peut envoyer deux codes : 200 (OK) ou 304 (résultat pas modifié). Si l'attribut never304 est faux, Solr va toujours renvoyer la réponse 200. Le corps de la balise httpCaching peut alors contenir les informations relatives à l'en-tête renvoyé. On peut, par exemple, y rajouter l'age maximal du cache (dans la balise-enfant : <cacheControl>max-age=43200, must-revalidate</cacheControl>





  10. <requestHandler />
    Le gestionnaire des requêtes permet de décrire le comportement de Solr pour certaines URLs. Grâce à lui on peut, par exemple, appliquer le comportement différent pour les requêtes contenant /query et /select. Dans notre cas, pour le premier type de la requête, on renvoie la réponse en JSON tandis que pour l'autre en XML. Les différences de paramétrage se situent au niveau de la liste de configuration, représentée par la balise <lst />.


  11. <queryResponseWriter />
    Cette balise définit la classe qui s'occupera de construire la réponse renvoyée au client. Chaque écrivain est identifié par l'attribut name. On peut l'appeler directement en spécifiant le paramètre "wt" dans la requête. Si l'attribut default est présent dans la balise et est true, il indique l'écriteur par défaut.
    En fonction de l'écrivain on peut déterminer les paramètres supplémentaires. Pour la réponse JSON on peut spécifier le Content-type. Pour XSLT, on peut indiquer le temps de cache.


Et voici le fichier complet :

<?xml version='1.0' encoding='utf-8'?>
<config>
<luceneMatchVersion>LUCENE_CURRENT</luceneMatchVersion>

<lib dir="/home/bartosz/workspace/world/WEB-INF/lib" />

<dataDir>${solr.data.dir}</dataDir>

<directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.StandardDirectoryFactory}"/>

<codecFactory class="solr.SchemaCodecFactory"/>


<schemaFactory class="ClassicIndexSchemaFactory"/>

<indexConfig>
<maxIndexingThreads>4</maxIndexingThreads>
<lockType>${solr.lock.type:native}</lockType>
<unlockOnStartup>false</unlockOnStartup>
</indexConfig>

<updateHandler class="solr.DirectUpdateHandler2">
<updateLog>
<str name="dir">${solr.ulog.dir:}</str>
</updateLog>

<autoCommit>
<maxTime>${solr.autoCommit.maxTime:15000}</maxTime>
<openSearcher>false</openSearcher>
</autoCommit>
</updateHandler>

<query>
<filterCache class="solr.FastLRUCache" size="512" initialSize="512" autowarmCount="0"/>
<queryResultCache class="solr.LRUCache" size="512" initialSize="512" autowarmCount="0"/>
<documentCache class="solr.LRUCache" size="512" initialSize="512" autowarmCount="0"/>
</query>

<requestDispatcher handleSelect="false" >
<requestParsers enableRemoteStreaming="true"
multipartUploadLimitInKB="2048000"
formdataUploadLimitInKB="2048"
addHttpRequestToContext="true"/>
<httpCaching never304="true" />
</requestDispatcher>

<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int>
<str name="df">text</str>
</lst>
</requestHandler>
<requestHandler name="/query" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<str name="wt">json</str>
<str name="indent">true</str>
<str name="df">text</str>
</lst>
</requestHandler>
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">./data-config.xml</str>
</lst>
</requestHandler>
<requestHandler name="/update/json" class="solr.JsonUpdateRequestHandler">
<lst name="defaults">
<str name="stream.contentType">application/json</str>
</lst>
</requestHandler>
<queryResponseWriter name="json" class="solr.JSONResponseWriter">
<str name="content-type">text/plain; charset=UTF-8</str>
</queryResponseWriter>
</config>


Le schéma des indexes
Cependant ce fichier de configuration ne suffit pas pour mettre en place Solr. En fait, il lui manque un compagnon, très important, car décrivant tout le schéma des données sauvegardées dans les indexes. Il s'agit du fichier appelé schema.xml et placé dans le même répertoire que la configuration de base. On l'analysera de la même manière que le fichier précédent :



  1. <fields />
    Regroupe tous les champs compris dans les documents.


    • <field />
      Parmi les attributs qui le caractérisent, il faut garder en tête les principaux :
      - name : nom qui peut être utilisé dans la recherche
      - type : type de donnée : chiffre, lettre...
      - indexed : si la valeur doit être indexée; si faux, la valeur ne sera pas indexée, mais pourra être retournée dans la réponse
      - stored : si la valeur doit être indexée, mais ne doit pas être retournée dans la réponse - peut s'appliquer à des champs d'une grande largeur
      - required : le champ obligatoire. Son absence déclenchera une erreur.
      - termVector : si true, permet d'analyser les statistiques d'un champ dans le document (par exemple fréquence d'apparition dans un document etc.).





  2. <uniqueKey />
    Ce champ indique le champ unique par document.


  3. <types />
    Ici on indique les types de données qu'on souhaite stocker dans Solr :


    • <fieldType />
      Un type du champ. Il peut prendre comme paramètre :
      - name : le nom du champ (string, int...).
      - class : la classe qui est en charge du champ.
      - sortMissingLast : si true, il provoque que les documents n'ayant pas ce champ renseigné, viennenet après les résultats avec ce champ dans les réslultats de la recherche.
      - precisionStep : valeur renseignée en bits, va provoquer l'indexation de plus d'éléments par une donnée. Si 0, cette configuration est désactivée.
      - positionIncrementGap : autrement dit, un espacement entre les mêmes champs; il permet d'éviter les soucis de résultats dans les situations où l'on recherche deux valerus qui se succèdent (par exemple : en ayant deux champs "well" et "done") répondent à une requête (en occurrence, "well done").



      • <analyzer />
        Chaque champ peut contenir une sorte de formatteur. Le formatteur peut être accompagné d'un tokenizer (transforme une chaîne de caractères) et d'un filtre (par exemple pour blacklister certains mots). L'analyzer peut prendre un des deux types : query (concerne la requête) ou index (concerne l'indéxation).





A travers cet article on a pu voir la configuration de base de Solr. La configuration qui est assez rapide à écrire, dont le coeur tourne autour des gestionnaires des requêtes et des constructeurs des réponses.
Bartosz KONIECZNY 08-09-2013 17:22 Solr
Moi

Développeur d'applications Internet et journaliste passionné par l'adjectif français. Un aigle polonais orienté vers la progression, volant très haut et écoutant du zouk après les matches du foot français.

Vous appréciez mon travail ?

Pour contribuer au développement de ce site, ou pour remercier pour des articles rédigés, vous pouvez faire un don.

Un conseil Android

Un problème de connexion à un web service ou à l'internet.

Vérifiez dans votre AndroidManifest.xml si la balise suivante est présente :
<uses-permission android:name="android.permission.INTERNET" />