Installation du moteur de recherche SolR sous Windows / Tomcat

Classé dans : Web | 3 commentaires

mardi 16 mars 2010

SolR est un moteur de recherche Open Source basé sur Lucene qui permet d'indexer tous types de documents (bases de données, fichiers,...) et d'exécuter des requêtes dessus. Il est très puissant et nous l'avons mis en place sur un site de petites annonces.

Nous allons détailler dans cet article comment l'installer sous Windows avec le serveur Tomcat et comment le remplir puis l'interroger.

::TOC::

Installation initiale

Prérequis

  • Une JRE (ici, version 6 update 18)
    Attention, sur www.java.com, la version par défaut est 32bits, pensez à bien choisir la version 64 bits i le serveur est en 64 bits.

Installation de Tomcat

  • Installez Tomcat à partir du fichier exécutable d'install (32-bit/64-bit Windows Service Installer).
  • Définissez un login  (administrateur, par ex) et un mot de passe pour le manager.
  • Lancez Tomcat puis arrêtez-le (ceci permet de créer les dossiers Catalina\localhost dans le dossier conf).
  • Vérifiez dans le Gestionnaire de services que le service se lance bien automatiquement avec Windows (il est par défaut en démarrage manuel).

Préparation de SOLR

  • Téléchargez la dernière version de Solr (ici, 1.4.0) au format zip sur http://www.apache.org/dyn/closer.cgi/lucene/solr/ 
  • Dézipper la version binaire de SOLR dans C:\apache-solr-1.4.0 (on trouve dans ce dossier les dossiers client, contrib, examples,…) => Appelons ce dossier <src>.
  • Créez un dossier C:\solr . Appelons ce dossier <home>
  • Copier le dossier <src>/examples/webapps dans <home> (le dossier webapps contient le fichier solr.war)
  • Créer dans <home> un dossier par index (ex : index1, index2)
  • Copier dans chacun d'eux le contenu du dossier <src>/examples/solr/(dossiers bin et conf)
  • Créer dans chacun d'eux un dossier data

Références

Configuration de TomCat

Chemin vers SOLR dans les paramètres de Tomcat

  • Dans le manager TomCat (menu Démarrer => Configure Tomcat  ou C:\Program Files\Apache Software Foundation\Tomcat 6.0\bin\ tomcat6w.exe) allez dans l'onglet Java.
  • Ajoutez à la fin des Java options la ligne suivante :
    -Dsolr.solr.home=<home>
    (sans le \ final).

Fichiers de conf iguration Tomcat

  • Editer le fichier C:\Program Files\Apache Software Foundation\Tomcat 6.0\conf\server.xml :
    Ajouter URIEncoding="UTF-8"  au noeud <Connector port="8080" protocol="HTTP/1.1"... qui doit désormais ressembler à ceci :
    <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/>
  • Dans C:\Program Files\Apache Software Foundation\Tomcat 6.0\conf\Catalina\localhost , créez un fichier solr.xml avec le contenu suivant  :
    <Context docBase="<home> \webapps\solr.war" debug="0" crossContext="true" >
        <Environment name="solr/home" type="java.lang.String" value="<home>\" override="true" />
    </Context>

Fichier de configuration SOLR

Dans <home>, créer le fichier solr.xml avec le contenu suivant :
<solr persistent="true" sharedLib="lib">
<cores adminPath="/admin/cores">
<core name="index1" instanceDir="index1" />
<!--<core name="index2" instanceDir="index2"/>-->
</cores>
</solr>

Ce fichier permet de configurer les cœurs d'exécution de chaque index SolR.
Pour ce faire, il suffit d'ajouter une ligne <core name=""… pour chaque index.
  • core name : nom du cœur
  • core instance : nom du dossier correspondant dans <home>

Tests

  • Redémarrez Tomcat
  • Lancez l'url suivante pour vérifier que tout est ok :
    http://localhost:8080/solr/index1/admin/
  • Normalement, les cores apparaissent dans la ligne Cores (si il y en a plusieurs de définis)
  • En cas de problème, consultez les logs de Tomcat dans C:\Program Files\Apache Software Foundation\Tomcat 6.0\logs

Configuration de SolR

A faire pour chaque index. les fichiers de configuration se trouve dans <home>\<index>\conf

schema.xml

Le fichier schema.xml permet de paramétrer les champs à indexer (dans le nœud fields) et les types de champ ainsi que le paramétrage de leur fonctionnement d'indexation (dans le noeud types).

Je vous renvoie à la documentation pour plus de détail mais voici quelques conseils:  
  • On ne peut indexer que des champs de type solr.TextField.
  • Pour chaque champ, on peut indiquer si il est indexé (indexed="true") et/ou si il est stocké tel quel (stored="true").
Dans notre cas, nous avons défini plusieurs champs :
Nom Utilisation Type Indexé Stocké
monID Clé unique solr.TrieLongField oui oui
monTexte Bloc de texte qui sera affiché dans les recherches solr.TextField non oui
champ1 Bloc servant pour les recherches (priorité élevée) solr.TextField oui non
champ2 Bloc servant pour les recherches (priorité basse) solr.TextField oui non
rubriqueID La rubrique dans laquelle est classé le document solr.TrieLongField non oui


Ce qui nous donne la configuration suivante :
<fields>
    <field name="monID" type="long" indexed="true" stored="true" required="true"/>
    <field name="rubriqueID" type=" long " indexed="true" stored="true" required="true"/>
    <field name="monTexte" type="text" indexed="false" stored="true" required="true"/>
    <field name="champ1" type="text" indexed="true" stored="false" required="true"/>
    <field name="champ2" type="text" indexed="true" stored="false" required="false"/>

    <dynamicField name="*" type="ignored" />
</fields>

<uniqueKey>monID</uniqueKey>
<defaultSearchField>champ1</defaultSearchField>
C'est dans la section <types> que l'on définit les paramètres d'indexation de chaque type de champ, en paramétrant les analyzers .
Voici un exemple de notre champ de type texte :
<fieldType name="text_fr" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ISOLatin1Accent.txt"/>
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<!--<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords/stopwords_fr.txt" enablePositionIncrements="true" />-->
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.SnowballPorterFilterFactory" language="French" protected="protwords.txt"/>
</analyzer>

<analyzer type="query">
<charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ISOLatin1Accent.txt"/>
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<!--<filter class="solr.SynonymFilterFactory" synonyms="synonyms/synonyms_fr.txt" ignoreCase="true" expand="true"/>-->
<!--<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords/stopwords_fr.txt" enablePositionIncrements="true"/>-->
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.SnowballPorterFilterFactory" language="French" protected="protwords.txt"/>
</analyzer>
</fieldType>

solrconfig.xml

  • Commentez la ligne suivante :
    <dataDir>${solr.data.dir:./solr/data}</dataDir>
    Ceci permet de créer l'index dans le sous-dossier data et non dans le dossier par défaut (C:\Program Files\Apache Software Foundation\Tomcat 6.0\solr\data)

Vérifier la configuration

  • Relancez Tomcat pour prendre en compte les modifications.
  • Vérifiez que les champs sont bons dans le Shema Browser :
    http://localhost:8080/solr/index1/admin/schema.jsp 
  • En cas d'erreur, aller voir dans les logs de Tomcat.

Mise à jour de l'index

La mise à jour de l'index (ajout, mise  à jour, suppression) se fait très simplement par l'envoi en POST d'un flux xml. Chaque élément de l'index est appelé document.

Ajout,  modification.

La syntaxe est la même pour les 2 actions. En fait, si le document existe déjà (basé sur sa clé unique), il sera mis à jour, sinon il sera ajouté.
On peut ajouter/mettre à jour plusieurs documents en une seule fois.
Voici la structure du fichier xml à envoyer (basé sur notre exemple ci-dessus) :
<add>
<doc>
<field name="monID">12</field>
<field name="rubriqueID">5</field>
<field name="monTexte">le texte à afficher</field>
<field name="champ1">mots-clé principaux</field>
<field name="champ2">mots-clé secondaires</field>
</doc>
<doc>
<field name="monID">13</field>
<field name="rubriqueID">1</field>
<field name="monTexte">le texte à afficher</field>
<field name="champ1">mots-clé principaux</field>
<field name="champ2">mots-clé secondaires</field>
</doc>
</add>
Il faut ensuite envoyer en POST un autre flux xml contenant une commande COMMIT :
Le contenu du flux xml est tout simple :
<commit/>
On peut également appeler une commande pour optimiser l'index :
<optimize/>

Suppression de documents

Le principe est le même : on envoie dans un premier temps le flux xml des documents à supprimer, puis on effectue un commit.

Le flux xml pour la suppression est simple :
<delete>
<id>12</id>
<id>13</id>
</delete>
Notez que l'on utilise le champ id et non le nom du champ que l'on a donné à notre clé unique (monID).

Exemple d'appel à SolR en ASP

Voici un exemple de code en ASP pour ajouter et supprimer des documents. Vous remarquerez que l'on peut très bien envoyer dans un même flux xml des ajouts et des suppressions.
' On crée le xml
xml = "<add>"
xml = xml & "<doc>"
xml = xml & "<field name=""monID"">12</field>"
xml = xml & "<field name=""rubriqueID"">5</field>"
xml = xml & "<field name=""monTexte"">" & Server.HtmlEncode("le texte à afficher") & "</field>"
xml = xml & "<field name=""champ1"">" & Server.HtmlEncode("mots-clé principaux") & "</field>
xml = xml & "<field name=""champ2"">" & Server.HtmlEncode("mots-clé secondaires") & "</field>"
xml = xml & "</doc>"
xml = xml & "</add>"

xml = xml & "<delete>"
xml = xml & "<id>13</id>"
xml = xml & "</delete>"


' On envoie le contenu Xml vers SolR
Set oXml = Server.CreateObject("MSXML2.ServerXMLHTTP.3.0")

oXml.Open "POST", "http://localhost:8080/solr/index1/update", False
oXml.setRequestHeader "Content-Type", "text/xml"
oXml.Send xml
If oXml.readyState <> 4 Then oXml.waitForResponse 10
retour = solrRetour(oXml.responseText)


' Commit
If retour = 0 Then
oXml.Open "POST", " http://localhost:8080/solr/index1/update", False
oXml.setRequestHeader "Content-Type", "text/xml"
oXml.Send "<commit/>"
If oXml.readyState <> 4 Then oXml.waitForResponse 10
retour = solrRetour(oXml.responseText)
End If

' TRAITEMENT DU FLUX XML DE RETOUR DES COMMANDES SOLR
'----------------------------------------------------
Function solrRetour(xml)
Dim oXml, Root, lst, retour

Set oXml = Server.CreateObject("MSXML.DOMDocument")
oXml.Async=False

If Not oXml.loadXml(xml) Then
retour = -1
Else

Set Root = oXml.documentElement
Set lst = Root.selectSingleNode("lst")
retour = lst.selectSingleNode("int[@name='status']").text

End If

solrRetour = retour
End Function

Références

Exécuter des requêtes

Là aussi, l'exécution de requêtes est très simple : il suffit d'interroger une page et de récupérer le contenu du flux xml.

Structure de la requête

Voici un exemple d'url :
http://localhost:8080/solr/index1/select?qt=dismax&q=les+mots+cles&qf=champ1^1+champ2^0.6&start=0&rows=25&fl=monID,monTexte,score&fq=rubriqueID:5
Détaillons les paramètres :
Champ Valeur
qt (query type) dismax : ce type de requête permet la pondération des champs de recherche
q (query) La liste des mots clés
qf (query fields) Liste des champs dans lesquels doit s'effectuer la recherche (champs indexés uniquement).
On peut pondérer ces champs en ajoutant ^x où x est le coefficient de pondération.
start, rows Permet de ne récupérer qu'une partie des résultats pour générer une pagination par exemple.
- start est la position du 1ere résultat à afficher
- rows est le nombre de résultats à récupérer.
fl (field list)  Liste des champs à renvoyer dans le flux xml, séparés par des virgules.
Le champ spécial score renvoit le score calculé poar SolR
fq (filter query) Permet de restreindre la recherche à certaines valeurs de certains champs (ici, on ne récupère que les documents de la rubrique n° 5)

Exemple de code en ASP :
url = "http://localhost:8080/solr/index1/select?..."

Set oXmlSolr = Server.CreateObject("MSXML2.ServerXMLHTTP")
Set oXml = Server.CreateObject("MSXML.DOMDocument")

oXml.Async=False
oXmlSolr.Open "GET", url ,False
oXmlSolr.Send()
Set Root = oXml.documentElement
Set result = Root.selectSingleNode("result")
nbResults = result.GetAttribute("numFound")

For Each doc in result.ChildNodes
Response..Write (doc.selectSingleNode("str[@name='monTexte']").text)
Next
http://vm-win2003-01:8080/solr/aafr/select?indent=on&q=chargeur&rows=10&fl=*+score&qt=dismax&qf=Champ1^1+Champ2^0.6+Champ3^0.3
http://vm-win2003-01:8080/solr/aafr/select?q=moissonneuse&fq=&start=0&rows=100&fl=produitID,HTML,score&qt=dismax&qf=Champ1^0.6+Champ2^0.3+Champ3^0.1

Références

Réplication


On considère pour cette étape qu'aucun index n'a encore été généré (dossier data vide).

Configuration du serveur maître

  • Editez le fichier solrConfig.xml et décommentez et adaptez la partie suivante: 
    (la section slave doit être correctement configurée avec l'adresse du maître et commentée.)
    <requestHandler name="/replication" class="solr.ReplicationHandler" > 
    <lst name="master">
    <str name="replicateAfter">commit</str>
    <str name="replicateAfter">optimize</str>
    <str name="replicateAfter">startup</str>
    <str name="confFiles">solrconfig_slave.xml:solrconfig.xml,schema.xml</str>
    </lst>
    <!--
    <lst name="slave">
    <str name="masterUrl">http://192.168.2.35:8080/solr/index1/replication</str>
    <str name="pollInterval">00:00:60</str>
    </lst>
    -->
    </requestHandler>
  • Dupliquez le fichier solrconfig.xml en solrconfig_slave.xml.
  • (ceci permet d'appliquer toutes les modifications  sur le maître et de répliquer la configuration sur les esclaves (le fichier solrconfig_slave.xml sera automatiquement renommé en solrconfig.xml).
  • Editez le fichier solrconfig_slave.xml, commentez la partie master et décommentez la partie slave.
  • Redémarrez Tomcat.
Attention : Toute modif apportée à solrconfig.xml devra également l'être sur solrconfig_slave.xml.

Sur l'esclave

  • Installez Tomcat et Solr en suivant la procédure jusqu'à l'étape "Configuration de Tomcat" incluse mais ne redémarrez pas Tomcat tout de suite.
  • Recopiez lecontenu du dossier de l'index du maître dans le dossier de l'index correspondant sur l'esclave.
  • Renommez solrconfig_slave.xml en sorlconfig.xml.
  • Lancez Tomcat.
  • Vérifiez que la réplication fonctionne en appelant cette url directement sur le serveur esclave :
    http://<ip_esclave>:8080/solr/aa/admin/replication/

Références

Compléments d'information

Gestion des accents et similitudes

ex : élévateur, elevateur, élevateur
Utilisez un champ text spécifique avec le filtre suivant (analyzer index + query) :
<charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ISOLatin1Accent.txt"/>

Configurer les index pour une indexationavec une base de données MySQL

On peut indexer directement une base de données MySQL. Voici une ébauche concernant la façon de paramétrer l'indexation MySQL (non
testée).
Récupérer le driver JDBC MySQL
Copier le fichier mysql-connector-java-<version>-bin.jar dans <home>\lib.
Paramétrer l'accès aux données
  • Dans le dossier conf, créez un fichier dataconfig.xml, copiez le code ci-dessous et adaptez-le (champs en rouge) :
    <?xml version="1.0" encoding="UTF-8"?>
    <dataConfig>
    <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/database" user="user" password="password"/>

    <document name="doc">
    <entity name="jos_content"
    query="SELECT * FROM matable WHERE state=1"
    deltaImportQuery="SELECT * FROM matable WHERE tableID='${dataimporter.delta.job_jobs_id}'"
    deltaQuery="SELECT tableID FROM matable WHERE modified > '${dataimporter.last_index_time}'">

    <field column ="tableID" name="monID" />
    <field column="tableTexte" name="monTexte" />
    <field column="rubriqueID" name="rubriqueID" />
    </entity>
    </document>
    </dataConfig>
  • Dans le fichier solrconf.xml,  ajoutez le requestHandler suivant :
    <requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
    <lst name="defaults">
    <str name="config">dataconfig.xml</str>
    </lst>
    </requestHandler>
  • Dans le fichier solrconf.xml,  commentez la ligne <dataDir>.
  • Lancer l'indexation complète avec l'url suivante :
    http://vm-win2003-01:8080/solr/aafr/dataimport?command=full-import 
Problème de mémoire 
Si vous obtenez un message d'erreur indiquant un problème de mémoire, ajouter batchSize="-1" à la connexion mysql dans dataconfig.xml, ce qui nous donne :
<dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/database" batchSize="-1" user="user" password="password"/>
Références




Commentaires

Le 07 janvier 2012 Dépannage informatique a dit :

Merci

Le 28 juin 2013 Dominique a dit :

Bonjour,

les liens vers http://www.zoonix.fr/... ne fonctionnent plus, il faut utiliser http://www.eolya.fr/.. à la place.

merci

Le 05 juillet 2013 fred a dit :

@Dominique :Merci, les liens sont corrigés :-)

Fil Rss des commentaires de cet article

Ecrire un commentaire

Les commentaires sont modérés et je ne publie pas les messages à caractère publicitaire. Inutile donc de vous acharner ;-)




Quelle est la dernière lettre du mot mifygn ? :