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
- http://www.eolya.fr/2008/12/08/introduction-a-solr-installation-et-configuration-1/
- http://www.eolya.fr/2009/05/10/introduction-a-solr-installation-et-configuration-2/
- http://drupal.org/node/532584
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 :Ce fichier permet de configurer les curs d'exécution de chaque index SolR.<solr persistent="true" sharedLib="lib">
<cores adminPath="/admin/cores">
<core name="index1" instanceDir="index1" />
<!--<core name="index2" instanceDir="index2"/>-->
</cores>
</solr>
Pour ce faire, il suffit d'ajouter une ligne <core name="" pour chaque index.
- core name : nom du cur
- 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>\confschema.xml
Le fichier schema.xml permet de paramétrer les champs à indexer (dans le nud 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").
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>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 .
<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>
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>Il faut ensuite envoyer en POST un autre flux xml contenant une commande COMMIT :
<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>
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>Notez que l'on utilise le champ id et non le nom du champ que l'on a donné à notre clé unique (monID).
<id>12</id>
<id>13</id>
</delete>
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:5Dé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?..."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
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?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
- http://wiki.apache.org/solr/SolrReplication
- http://techgurulive.com/2009/12/14/how-to-configure-apache-solr-replication/
Compléments d'information
Gestion des accents et similitudes
ex : élévateur, elevateur, élevateurUtilisez 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 (nontesté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
- http://www.cabotsolutions.com/blog/200905/using-solr-lucene-for-full-text-search-with-mysql/
- http://wiki.apache.org/solr/DataImportHandlerFaq
Commentaires