<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Miximum &#187; lucène</title>
	<atom:link href="http://www.miximum.fr/tag/lucene/feed" rel="self" type="application/rss+xml" />
	<link>http://www.miximum.fr</link>
	<description>Le blog d&#039;un ingénieur web freelance</description>
	<lastBuildDate>Wed, 16 Nov 2011 16:25:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Quel moteur de recherche pour votre site ?</title>
		<link>http://www.miximum.fr/methodes-et-outils/322-quel-moteur-de-recherche-pour-votre-site</link>
		<comments>http://www.miximum.fr/methodes-et-outils/322-quel-moteur-de-recherche-pour-votre-site#comments</comments>
		<pubDate>Fri, 28 Aug 2009 14:36:07 +0000</pubDate>
		<dc:creator>thibault</dc:creator>
				<category><![CDATA[Méthodes et outils]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[lucène]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[solr]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.miximum.fr/?p=322</guid>
		<description><![CDATA[photo credit&#160;: Kaptain Kobold Il est loin le temps ou les internautes, en arrivant sur un site, parcouraient patiemment les divers menu jusqu&#8217;&#224; trouver le contenu qui les int&#233;resse. Qui proc&#232;de encore comme &#231;a aujourd&#8217;hui&#160;? On s&#8217;imagine mal naviguer dans une arborescence pour trouver un article sur des sites comme wikipedia ou ebay. L&#8217;usage, de [...]]]></description>
			<content:encoded><![CDATA[<div class="postimg alignleft"><a href="http://www.flickr.com/photos/95492938@N00/83359336/" title="It's Murder, Watson!" target="_blank"><img src="http://farm1.static.flickr.com/42/83359336_7170ce67a1_m.jpg" alt="It's Murder, Watson!" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-nc-sa/2.0/" title="Attribution-NonCommercial-ShareAlike License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a> <a href="http://www.photodropper.com/photos/" target="_blank">photo</a> credit&nbsp;: <a href="http://www.flickr.com/photos/95492938@N00/83359336/" title="Kaptain Kobold" target="_blank">Kaptain Kobold</a></small></div>
<p>Il est loin le temps ou les internautes, en arrivant sur un site, parcouraient patiemment les divers menu jusqu&#8217;&agrave; trouver le contenu qui les int&eacute;resse. Qui proc&egrave;de encore comme &ccedil;a aujourd&#8217;hui<span class="fine">&nbsp;</span>? On s&#8217;imagine mal naviguer dans une arborescence pour trouver un article sur des sites comme wikipedia ou ebay. L&#8217;usage, de nos jours, est &agrave; la rapidit&eacute;, que dis-je, &agrave; l&#8217;imm&eacute;diatet&eacute;&nbsp;: une petite recherche et hop<span class="fine">&nbsp;</span>! Le contenu d&eacute;sir&eacute; nous tombe tout cru dans le bec.</p>
<p>D&#8217;o&ugrave; l&#8217;importance cruciale du moteur du recherche, sans lequel un site digne de ce nom ne peut se pr&eacute;tendre utilisable. Et qui dit moteur de recherche, dit prise de t&ecirc;te pour les SI, car les solutions sont nombreuses et h&eacute;t&eacute;rog&egrave;nes. Je vous propose donc un petit tour d&#8217;horizon de quelques technologies destin&eacute;es &agrave; int&eacute;grer des moteurs de recherches sur vos sites.</p>
<h2>Google Search</h2>
<p>Bon, commen&ccedil;ons par la solution b&ecirc;te et m&eacute;chante. Tout le monde connait Google<span class="fine">&nbsp;</span>? Et bien Google fournit la possibilit&eacute; d&#8217;int&eacute;grer son fameux moteur de recherche sur (presque) n&#8217;importe quel site. On copie-colle un petit bout de code sur sa page, et hop<span class="fine">&nbsp;</span>!</p>
<p>L&#8217;avantage<span class="fine">&nbsp;</span>? C&#8217;est la solution la plus simple. Vous n&#8217;avez &agrave; vous occuper de rien. Les inconv&eacute;niants<span class="fine">&nbsp;</span>? Ils sont nombreux<span class="fine">&nbsp;</span>! Vous n&#8217;avez aucun contr&ocirc;le sur les retours, une emprise limit&eacute;e sur la mise en page des r&eacute;sultats, et puis, vous n&#8217;avez bien entendu aucun moyen de contr&ocirc;ler l&#8217;indexation du site. &Agrave; r&eacute;server aux &laquo;&nbsp;sites persos&nbsp;&raquo; des webmasters fain&eacute;ants ou press&eacute;s.</p>
<h2>Recherche full text MySQL</h2>
<p>Retour aux fondamentaux. La plupart des SGBD majeurs fournissent des <a href="http://dev.mysql.com/doc/refman/5.0/fr/fulltext-search.html">index pour la recherche full text</a>, c&#8217;est &agrave; dire qu&#8217;il est possible, via une requ&ecirc;te sp&eacute;cifique, d&#8217;effectuer une recherche dans un ensemble de champs de types textes.</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><a href="http://search.mysql.com/search?site=refman-51&amp;q=SELECT&amp;lr=lang_en"><span class="kw1">SELECT</span></a> <span class="sy1">*</span> <a href="http://search.mysql.com/search?site=refman-51&amp;q=FROM&amp;lr=lang_en"><span class="kw1">FROM</span></a> products
    <span class="sy1">-&gt;</span> <a href="http://search.mysql.com/search?site=refman-51&amp;q=WHERE&amp;lr=lang_en"><span class="kw1">WHERE</span></a> <a href="http://search.mysql.com/search?site=refman-51&amp;q=MATCH&amp;lr=lang_en"><span class="kw1">MATCH</span></a> <span class="br0">&#40;</span>title<span class="sy2">,</span>description<span class="br0">&#41;</span> AGAINST <span class="br0">&#40;</span><span class="st0">'open moko'</span><span class="br0">&#41;</span><span class="sy2">;</span></pre></div></div>

<p>Avantage&nbsp;: la solution est pratique, lorsque le besoin est simple et tr&egrave;s sp&eacute;cifique. En revanche, il faudra mettre les mains dans le camboui, et la solution peut devenir difficile &agrave; mettre en &oelig;uvre et maintenir lorsque le besoin est un peu plus complexe. Et puis, selon la volum&eacute;trie, les perfs ne sont pas au top. Au final, les possibilit&eacute;s restent un peu limit&eacute;es.</p>
<h2>Doctrine Search Behavior</h2>
<p>Je mentionne la solution qui me semble injustement peu connue. L&#8217;ORM Doctrine, embarqu&eacute; avec <a href="http://www.miximum.fr/tag/symfony">symfony</a>, <a href="http://www.doctrine-project.org/documentation/manual/1_1/en/searching">propose un <i>behavior</i> qui permet de g&eacute;n&eacute;rer automatiquement un index full text</a>.</p>
<p>Une solution pratique et rapide pour g&eacute;rer un moteur de recherche sur des sites batis avec ce framework.</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"># schema.yml
&nbsp;
Product:
  actAs:
    Searchable:
      fields: [title, description]
# ...</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="re0">$products</span> <span class="sy0">=</span> Doctrine<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span><span class="st_h">'product'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">search</span><span class="br0">&#40;</span><span class="st_h">'clavier pour blonde'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>

<p>C&#8217;est facile, c&#8217;est rapide, que demande le peuple<span class="fine">&nbsp;</span>?</p>
<h2>MNoGoSearch</h2>
<p><a href="http://www.mnogosearch.org/">mnoGoSearch</a> est un moteur de recherche &eacute;crit en C et compos&eacute; de deux parties&nbsp;: d&#8217;une part, un crawler (indexeur) capable de naviguer sur des pages html ou en texte pur, et une interface de requ&ecirc;te pour effectuer les recherches.</p>
<p>MnogoSearch fonctionne &laquo;&nbsp;&agrave; la Google&nbsp;&raquo;, le robot explore r&eacute;guli&egrave;rement votre contenu, et construit son index ainsi. L&#8217;avantage, c&#8217;est que vous d&eacute;tenez la main sur la configuration de l&#8217;indexeur. MnogoSearch est capable d&#8217;indexer des sites en plusieurs langues, des groupes de sites, supporte plusieurs bases de donn&eacute;es, et il vous sera possible d&#8217;effectuer vos requ&ecirc;tes via des fonctions PHP.</p>
<p>En bref, MnogoSearch est parfait si vous souhaitez mettre en place un moteur de recherche basique sur vos pages de contenu, tout en contr&ocirc;lant la teneur de votre index.</p>
<h2>Sphinx</h2>
<div class="postimg alignright"><a href="http://www.flickr.com/photos/17513020@N00/362900750/" title="Paraguayensis Kandinsky Detectivicus" target="_blank"><img src="http://farm1.static.flickr.com/100/362900750_5369302dde_m.jpg" alt="Paraguayensis Kandinsky Detectivicus" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-nc-sa/2.0/" title="Attribution-NonCommercial-ShareAlike License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a> <a href="http://www.photodropper.com/photos/" target="_blank">photo</a> credit&nbsp;: <a href="http://www.flickr.com/photos/17513020@N00/362900750/" title="julianrod" target="_blank">julianrod</a></small></div>
<p><a href="http://www.sphinxsearch.com/about.html">Sphinx est un autre moteur de recherche full text</a>, &eacute;crit en C++. Sa particularit&eacute;<span class="fine">&nbsp;</span>? Sphinx a &eacute;t&eacute; sp&eacute;cialement con&ccedil;u avec la performances &agrave; l&#8217;esprit. Si l&#8217;on en croit les benchmarks (j&#8217;avoue ne jamais l&#8217;avoir test&eacute; en personne), il poutre tout simplement les performances d&#8217;une recherche full text basique de mysql, et l&#8217;enl&egrave;ve honorablement sur mnogosearch.</p>
<p>Sphinx est donc capable d&#8217;indexer une &eacute;norme quantit&eacute; de documents (plusieurs gigas) &agrave; une grande rapidit&eacute;, et d&#8217;effectuer des recherches en un temps record. Il est capable d&#8217;indexer des donn&eacute;es provenant de plusieurs sources (c&#8217;est &agrave; dire, ce n&#8217;est pas qu&#8217;un crawler de pages web), et fournit des apis dans la plupart des langages majeurs.</p>
<p>Il est de plus relativement facile &agrave; mettre en place, ce qui en fait un bon choix de moteur de recherche. D&#8217;ailleurs, Sphinx est utilis&eacute; par des gros projets, tels que thepiratebay, mininova, craigslist, ou dailymotion.</p>
<h2>Luc&egrave;ne / Solr</h2>
<p>Alors l&agrave;, c&#8217;est la Rolls-Royce des moteurs de recherche. Luc&egrave;ne / Solr, &eacute;crit en Java, est sans doute le moteur de recherche libre le plus puissant du moment, fournissant toutes les fonctionnalit&eacute;s dont vous aviez r&ecirc;v&eacute; (requ&ecirc;tes bool&eacute;ennes, recherche par facette, r&eacute;plication, recherche distribu&eacute;e, etc.).</p>
<p>Pour &ecirc;tre exact, Luc&egrave;ne est la biblioth&egrave;que d&#8217;indexation et de r&eacute;cup&eacute;ration de donn&eacute;es. Solr, qui encapsule Luc&egrave;ne, est un moteur de recherche complet qui fournit une interface sous forme d&#8217;API XML / JSON.</p>
<p>Si vous souhaitez avoir une id&eacute;e de la mani&egrave;re dont on installe, configure et utilise Solr, je vous laisse consulter mon <a href="http://www.miximum.fr/tutos/192-integrer-solr-a-symfony">tutoriel sur l&#8217;int&eacute;gration de Solr &agrave; Symfony</a>.</p>
<p>Dans la plupart des cas, si votre besoin pr&eacute;sente un minimum de complexit&eacute;, Solr est la technologie &agrave; employer. L&#8217;inconv&eacute;niant<span class="fine">&nbsp;</span>? La configuration de la b&ecirc;te requiert certaines comp&eacute;tences, et les ressources n&eacute;cessaires &agrave; faire tourner le servlet java ne sont pas n&eacute;gligeables. Solr / Luc&egrave;ne reste, dans tous les cas, une excellente solution de moteur de recherche.</p>
<h2>Zend Luc&egrave;ne</h2>
<div class="postimg alignleft"><a href="http://www.flickr.com/photos/21943179@N06/3145066465/" title="el buscador" target="_blank"><img src="http://farm4.static.flickr.com/3295/3145066465_d8abbcbacb_m.jpg" alt="el buscador" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-nc-sa/2.0/" title="Attribution-NonCommercial-ShareAlike License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a> <a href="http://www.photodropper.com/photos/" target="_blank">photo</a> credit&nbsp;: <a href="http://www.flickr.com/photos/21943179@N06/3145066465/" title="Ignacio Conejo" target="_blank">Ignacio Conejo</a></small></div>
<p>Pour terminer notre tour d&#8217;horizon, j&#8217;aimerais introduire pour ceux qui ne connaissent pas le projet <a href="http://framework.zend.com/manual/fr/zend.search.lucene.html">Zend Luc&egrave;ne</a>. Zend Luc&egrave;ne, qui fait partie du Zend Framework, est une r&eacute;impl&eacute;mentation de Luc&egrave;ne en php. Le moteur de recherche fonctionne via une api php, et l&#8217;index g&eacute;n&eacute;r&eacute; est compatible avec Solr.</p>
<p>Cette solution est d&#8217;une extr&egrave;me simplicit&eacute;, il devient possible de mettre en place un moteur de recherche <i>full php</i> puissant avec une simplicit&eacute; et une rapidit&eacute; d&eacute;concertante. La documentation de Symfony fournit d&#8217;ailleurs <a href="http://www.symfony-project.org/jobeet/1_2/Doctrine/en/17">un exemple d&#8217;impl&eacute;mentation</a>.</p>
<p>En revanche, <a href="http://groups.google.com/group/symfony-users/browse_thread/thread/9c3a002438db9c0">les performances ne sont pas au rendez-vous</a>, et si le nombre d&#8217;objets index&eacute;s devient trop important (plusieurs dizaines de milliers), Zend Luc&egrave;ne deviendra vite inutilisable. &Agrave; r&eacute;server pour les besoins sp&eacute;cifiques, mais &agrave; la volum&eacute;trie limit&eacute;e.</p>
<h2>Conclusions</h2>
<p>J&#8217;esp&egrave;re que ce petit tour d&#8217;horizon, volontairement synth&eacute;tique, vous aura pr&eacute;sent&eacute; quelques informations utiles. Il reste tr&egrave;s incomplet, j&#8217;ai omis certaines technos qui me paraissaient peu fiables ou plus mises &agrave; jour, ou tout simplement parce que je ne les connais pas. Je me suis &eacute;galement limit&eacute; aux technologies libres.</p>
<p>Et vous, vous utilisez quoi pour votre moteur de recherche<span class="fine">&nbsp;</span>?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.miximum.fr/methodes-et-outils/322-quel-moteur-de-recherche-pour-votre-site/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Intégrer Solr à Symfony</title>
		<link>http://www.miximum.fr/tutos/192-integrer-solr-a-symfony</link>
		<comments>http://www.miximum.fr/tutos/192-integrer-solr-a-symfony#comments</comments>
		<pubDate>Wed, 13 May 2009 18:49:23 +0000</pubDate>
		<dc:creator>thibault</dc:creator>
				<category><![CDATA[Tutos]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[lucène]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[solr]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.miximum.fr/?p=192</guid>
		<description><![CDATA[photo credit&#160;: Desir&#233;e Delgado Salut la compagnie. Aujourd&#8217;hui, je vous propose un petit tutoriel ayant pour sujet&#160;: comment int&#233;grer Solr &#224; Symfony. Commen&#231;ons par pr&#233;senter nos diff&#233;rents combattants. &#192; ma gauche, Symfony, framework PHP que j&#8217;ai suffisamment pr&#233;sent&#233; pour qu&#8217;il soit n&#233;cessaire de me r&#233;p&#233;ter. &#192; ma droite, Solr (prononcez &#171;&#160;solar&#160;&#187;), un moteur de recherche [...]]]></description>
			<content:encoded><![CDATA[<div class="postimg alignleft"><a href="http://www.flickr.com/photos/28095040@N07/3273760287/" title="105/365... hum! it's elemental Mr. Watson!" target="_blank"><img src="http://farm4.static.flickr.com/3379/3273760287_102b47dcf0_m.jpg" alt="105/365... hum! it's elemental Mr. Watson!" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-nc-nd/2.0/" title="Attribution-NonCommercial-NoDerivs License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a> <a href="http://www.photodropper.com/photos/" target="_blank">photo</a> credit&nbsp;: <a href="http://www.flickr.com/photos/28095040@N07/3273760287/" title="Desir&eacute;e Delgado" target="_blank">Desir&eacute;e Delgado</a></small></div>
<p>Salut la compagnie. Aujourd&#8217;hui, je vous propose un petit tutoriel ayant pour sujet&nbsp;: comment int&eacute;grer <a href="http://lucene.apache.org/solr/">Solr</a> &agrave; <a href="http://www.symfony-project.org">Symfony</a>. Commen&ccedil;ons par pr&eacute;senter nos diff&eacute;rents combattants.</p>
<p>&Agrave; ma gauche, Symfony, framework PHP que j&#8217;ai <a href="http://www.miximum.fr/tag/symfony" >suffisamment pr&eacute;sent&eacute; pour qu&#8217;il soit n&eacute;cessaire de me r&eacute;p&eacute;ter</a>. </p>
<p>&Agrave; ma droite, Solr (prononcez &laquo;&nbsp;solar&nbsp;&raquo;), un moteur de recherche libre, extr&ecirc;mement puissant et aux multiples fonctionnalit&eacute;s, cod&eacute; en java, bas&eacute; sur <a href="http://lucene.apache.org/java/docs/index.html">la biblioth&egrave;que Luc&egrave;ne</a>. Houla<span class="fine">&nbsp;</span>! &mdash; me direz vous<span class="fine">&nbsp;</span>! Mais s&#8217;il est en java, comment peut-il fonctionner avec notre framework pr&eacute;f&eacute;r&eacute;<span class="fine">&nbsp;</span>? Et bien c&#8217;est parce que Solr fournit une api en HTTP/XML. On lui crache du xml, et il nous renvoie du xml (en fait, il peut m&ecirc;me nous renvoyer du php, comme nous le verrons).</p>
<p>Si vous avez suivi l&#8217;excellent tutoriel jobeet, vous aurez remarqu&eacute; qu&#8217;il <a href="http://www.symfony-project.org/jobeet/1_2/Doctrine/en/17">existe d&eacute;j&agrave; un tuto portant sur la mise en place d&#8217;un moteur de recherche en utilisant le composant Search du zend framework</a>.</p>
<p>Ledit composant est tout simplement une r&eacute;&eacute;criture en php de luc&egrave;ne. C&#8217;est la premi&egrave;re m&eacute;thode que j&#8217;ai employ&eacute; lorsqu&#8217;il m&#8217;a fallu mettre en place un moteur de recherche pour un projet perso. L&#8217;avantage de cette m&eacute;thode est qu&#8217;elle est particuli&egrave;rement simple et rapide &agrave; mettre en &oelig;uvre. On installe le zend framework, on copie-colle quelques lignes du tuto, et hop<span class="fine">&nbsp;</span>! On &agrave; un moteur &eacute;tonnament puissant.</p>
<p>Tout allait bien tant que le nombre d&#8217;objets index&eacute;s restait raisonnable (quelques centaines). Mais quelques jours plus tard, la base contenait plus de 60000 documents et la moindre recherche entra&icirc;nait un vautrage &eacute;hont&eacute; du serveur pour manque de ressource. <a href="http://groups.google.com/group/symfony-users/browse_thread/thread/9c3a002438db9c0">Il m&#8217;a donc fallu trouver une solution alternative</a>, et j&#8217;ai fini par tester Solr, qui &agrave; mon grand contentement donne d&#8217;excellents r&eacute;sultats.</p>
<p>Ainsi, avec Solr, une recherche parmi 60000 documents avec tri par pertinence ne n&eacute;cessite que quelques millisecondes, contre presque une minute pour Zend.</p>
<p>&Eacute;trangement, il ne semble pas exister de plugin tout fait. Voici donc la m&eacute;thode que j&#8217;ai utilis&eacute; pour mettre en place Solr sur un projet Symfony.</p>
<h2>Installation de Solr</h2>
<p>Le site de solr fournit un <a href="http://lucene.apache.org/solr/tutorial.html">tutoriel assez complet sur l&#8217;installation</a> de la b&ecirc;te, aussi ne d&eacute;taillerai-je pas l&#8217;op&eacute;ration plus que n&eacute;c&eacute;ssaire.</p>
<p>Commencez par r&eacute;cup&eacute;rer l&#8217;archive de la derni&egrave;re version, et d&eacute;compactez l&agrave; dans <em>/opt/solr</em>.</p>
<p>L&#8217;archive contient d&eacute;j&agrave; un projet exemple, que nous allons dupliquer pour nous en servir comme base.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw3">cd</span> <span class="sy0">/</span>opt<span class="sy0">/</span>solr
<span class="kw2">cp</span> <span class="re5">-a</span> example monprojet</pre></div></div>

<p>Il va nous falloir configurer le schema utilis&eacute; par le moteur pour indexer les donn&eacute;es. Disons, pour l&#8217;exemple, que notre projet symfony est un <em>flickr-like</em>, et que nous voulons indexer des photos avec un titre, une description et des tags.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">vi</span> <span class="sy0">/</span>opt<span class="sy0">/</span>solr<span class="sy0">/</span>monprojet<span class="sy0">/</span>solr<span class="sy0">/</span>conf<span class="sy0">/</span>schema.xml</pre></div></div>

<p>Le fichier est abondamment comment&eacute;. Grosso-modo, au d&eacute;but, on trouve la d&eacute;finition des diff&eacute;rents types de champs indexables. Ceux d&eacute;finis par d&eacute;faut conviendront tr&eacute;s bien pour aujourd&#8217;hui. Ensuite, on trouve la liste des champs proprement dite.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">   <span class="sc-1">&lt;!-- nos champs --&gt;</span>
   <span class="sc3"><span class="re1">&lt;field</span> <span class="re0">name</span>=<span class="st0">&quot;id&quot;</span> <span class="re0">type</span>=<span class="st0">&quot;string&quot;</span> <span class="re0">indexed</span>=<span class="st0">&quot;true&quot;</span> <span class="re0">stored</span>=<span class="st0">&quot;true&quot;</span> <span class="re0">required</span>=<span class="st0">&quot;true&quot;</span> <span class="re2">/&gt;</span></span>
   <span class="sc3"><span class="re1">&lt;field</span> <span class="re0">name</span>=<span class="st0">&quot;title&quot;</span> <span class="re0">type</span>=<span class="st0">&quot;text&quot;</span> <span class="re0">required</span>=<span class="st0">&quot;true&quot;</span> <span class="re2">/&gt;</span></span>
   <span class="sc3"><span class="re1">&lt;field</span> <span class="re0">name</span>=<span class="st0">&quot;description&quot;</span> <span class="re0">type</span>=<span class="st0">&quot;text&quot;</span> <span class="re0">required</span>=<span class="st0">&quot;false&quot;</span> <span class="re2">/&gt;</span></span>
&nbsp;
   <span class="sc-1">&lt;!-- il peut y avoir plusieurs tags --&gt;</span>
   <span class="sc3"><span class="re1">&lt;field</span> <span class="re0">name</span>=<span class="st0">&quot;tag&quot;</span> <span class="re0">type</span>=<span class="st0">&quot;text&quot;</span> <span class="re0">required</span>=<span class="st0">&quot;false&quot;</span> <span class="re0">multiValued</span>=<span class="st0">&quot;true&quot;</span> <span class="re2">/&gt;</span></span>
&nbsp;
    <span class="sc-1">&lt;!-- Ce champ contiendra la copie de tous les autres, pour faciliter la recherche --&gt;</span>
   <span class="sc3"><span class="re1">&lt;field</span> <span class="re0">name</span>=<span class="st0">&quot;global&quot;</span> <span class="re0">type</span>=<span class="st0">&quot;text&quot;</span> <span class="re0">required</span>=<span class="st0">&quot;false&quot;</span> <span class="re0">multiValued</span>=<span class="st0">&quot;true&quot;</span> <span class="re2">/&gt;</span></span>
&nbsp;
    <span class="sc-1">&lt;!-- le champ id représente la clé --&gt;</span>
    <span class="sc3"><span class="re1">&lt;uniqueKey<span class="re2">&gt;</span></span></span>id<span class="sc3"><span class="re1">&lt;/uniqueKey<span class="re2">&gt;</span></span></span>
&nbsp;
    <span class="sc-1">&lt;!-- si dans une recherche on ne spécifie aucun champ, on recherche dans tous les champs --&gt;</span>
    <span class="sc3"><span class="re1">&lt;defaultSearchField<span class="re2">&gt;</span></span></span>global<span class="sc3"><span class="re1">&lt;/defaultSearchField<span class="re2">&gt;</span></span></span>
&nbsp;
   <span class="sc-1">&lt;!-- On copie les champs --&gt;</span>
   <span class="sc3"><span class="re1">&lt;copyField</span> <span class="re0">source</span>=<span class="st0">&quot;title&quot;</span> <span class="re0">dest</span>=<span class="st0">&quot;global&quot;</span><span class="re2">/&gt;</span></span>
   <span class="sc3"><span class="re1">&lt;copyField</span> <span class="re0">source</span>=<span class="st0">&quot;description&quot;</span> <span class="re0">dest</span>=<span class="st0">&quot;global&quot;</span><span class="re2">/&gt;</span></span>
   <span class="sc3"><span class="re1">&lt;copyField</span> <span class="re0">source</span>=<span class="st0">&quot;tag&quot;</span> <span class="re0">dest</span>=<span class="st0">&quot;global&quot;</span><span class="re2">/&gt;</span></span></pre></div></div>

<p>Le reste du fichier peut (doit) &ecirc;tre laiss&eacute; tel quel. Nous allons activer le format de sortie php&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">vi</span> <span class="sy0">/</span>opt<span class="sy0">/</span>solr<span class="sy0">/</span>monprojet<span class="sy0">/</span>solr<span class="sy0">/</span>conf<span class="sy0">/</span>solrconfig.xml</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="sc-1">&lt;!-- décommentez les lignes suivantes --&gt;</span>
<span class="sc3"><span class="re1">&lt;queryResponseWriter</span> <span class="re0">name</span>=<span class="st0">&quot;php&quot;</span> <span class="re0">class</span>=<span class="st0">&quot;org.apache.solr.request.PHPResponseWriter&quot;</span><span class="re2">/&gt;</span></span>
<span class="sc3"><span class="re1">&lt;queryResponseWriter</span> <span class="re0">name</span>=<span class="st0">&quot;phps&quot;</span> <span class="re0">class</span>=<span class="st0">&quot;org.apache.solr.request.PHPSerializedResponseWriter&quot;</span>/</span></pre></div></div>

<p>Et puis, pour faire bonne mesure, nous allons configurer jetty (le serveur java inclus dans l&#8217;install) pour n&#8217;&eacute;couter que sur localhost (0.0.0.0 par d&eacute;faut, pas tr&eacute;s s&eacute;cure).</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">vi</span> <span class="sy0">/</span>opt<span class="sy0">/</span>solr<span class="sy0">/</span>monprojet<span class="sy0">/</span>etc<span class="sy0">/</span>jetty.xml</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">   <span class="sc3"><span class="re1">&lt;Call</span> <span class="re0">name</span>=<span class="st0">&quot;addConnector&quot;</span><span class="re2">&gt;</span></span>
      <span class="sc3"><span class="re1">&lt;Arg<span class="re2">&gt;</span></span></span>
          <span class="sc3"><span class="re1">&lt;New</span> <span class="re0">class</span>=<span class="st0">&quot;org.mortbay.jetty.bio.SocketConnector&quot;</span><span class="re2">&gt;</span></span>
            <span class="sc-1">&lt;!-- Ajoutez cette ligne --&gt;</span>
            <span class="sc3"><span class="re1">&lt;Set</span> <span class="re0">name</span>=<span class="st0">&quot;Host&quot;</span><span class="re2">&gt;</span><span class="re1">&lt;SystemProperty</span> <span class="re0">name</span>=<span class="st0">&quot;jetty.host&quot;</span> <span class="re0">default</span>=<span class="st0">&quot;localhost&quot;</span><span class="re2">/&gt;</span><span class="re1">&lt;/Set<span class="re2">&gt;</span></span></span>
            <span class="sc3"><span class="re1">&lt;Set</span> <span class="re0">name</span>=<span class="st0">&quot;port&quot;</span><span class="re2">&gt;</span><span class="re1">&lt;SystemProperty</span> <span class="re0">name</span>=<span class="st0">&quot;jetty.port&quot;</span> <span class="re0">default</span>=<span class="st0">&quot;8983&quot;</span><span class="re2">/&gt;</span><span class="re1">&lt;/Set<span class="re2">&gt;</span></span></span>
            <span class="sc3"><span class="re1">&lt;Set</span> <span class="re0">name</span>=<span class="st0">&quot;maxIdleTime&quot;</span><span class="re2">&gt;</span></span>50000<span class="sc3"><span class="re1">&lt;/Set<span class="re2">&gt;</span></span></span>
            <span class="sc3"><span class="re1">&lt;Set</span> <span class="re0">name</span>=<span class="st0">&quot;lowResourceMaxIdleTime&quot;</span><span class="re2">&gt;</span></span>1500<span class="sc3"><span class="re1">&lt;/Set<span class="re2">&gt;</span></span></span>
          <span class="sc3"><span class="re1">&lt;/New<span class="re2">&gt;</span></span></span>
      <span class="sc3"><span class="re1">&lt;/Arg<span class="re2">&gt;</span></span></span>
    <span class="sc3"><span class="re1">&lt;/Call<span class="re2">&gt;</span></span></span></pre></div></div>

<p>Et voil&agrave;<span class="fine">&nbsp;</span>! Nous sommes maintenant pr&ecirc;ts &agrave; lancer le bouzin&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw3">cd</span> <span class="sy0">/</span>opt<span class="sy0">/</span>solr<span class="sy0">/</span>monprojet
java <span class="re5">-jar</span> start.jar</pre></div></div>

<p>Pour info, solr place son index dans <em>/opt/solr/monprojet/solr/data/index</em>. Si l&#8217;index n&#8217;existe pas, il le cr&eacute;&eacute; automatiquement au d&eacute;marrage. Ce qui signifie que si vous souhaitez supprimer votre index pour repartir &agrave; z&eacute;ro, il vous suffit de virer le r&eacute;pertoire en question, et relancer solr.</p>
<p>Pour v&eacute;rifier que Solr est bien lanc&eacute;, connectez vous sur <a href="http://localhost:8983/solr/admin/">http://localhost:8983/solr/admin/</a> (si c&#8217;est une installation locale).</p>
<h2>L&#8217;int&eacute;gration dans Symfony</h2>
<div class="alignright postimg"><a href="http://www.flickr.com/photos/84095300@N00/209493486/" title="Sherlock Holmes outside Baker Street underground station" target="_blank"><img src="http://farm1.static.flickr.com/75/209493486_90b93b0beb_m.jpg" alt="Sherlock Holmes outside Baker Street underground station" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-nc-sa/2.0/" title="Attribution-NonCommercial-ShareAlike License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a> <a href="http://www.photodropper.com/photos/" target="_blank">photo</a> credit&nbsp;: <a href="http://www.flickr.com/photos/84095300@N00/209493486/" title="gregwake" target="_blank">gregwake</a></small></div>
<p>Ok, passons &agrave; l&#8217;int&eacute;gration dans Symfony. Il nous faut plusieurs choses&nbsp;:</p>
<ul>
<li>D&#8217;abord, quand nous ajoutons une photo dans la base, nous voulons qu&#8217;elle soit automatiquement index&eacute;e.</li>
<li>Quand nous la supprimons, nous voulons qu&#8217;elle soit&#8230; d&eacute;sindex&eacute;e (bravo ceux qui suivent).</li>
<li>Nous voulons avoir un beau moteur de recherche int&eacute;gr&eacute; &agrave; notre site (avec pagination des r&eacute;sultats, &ccedil;a serait cool)</li>
<li>En bonus, &eacute;tant donn&eacute; que nous partons d&#8217;une base existante, une petite t&acirc;che qui permettrait d&#8217;indexer d&#8217;un coup toutes les photos du site ne serait pas du luxe.</li>
</ul>
<p>&Ccedil;a fait pas mal de choses, non<span class="fine">&nbsp;</span>? Et bien, soyez heureux, car dans mon immense bont&eacute;, ces choses, je vais vous les servir sur un plateau<span class="fine">&nbsp;</span>! Oui Monsieur<span class="fine">&nbsp;</span>! Et gratuitement en plus<span class="fine">&nbsp;</span>! C&#8217;est-y-pas la belle vie, &ccedil;a<span class="fine">&nbsp;</span>?</p>
<h2>Indexation, desindexation, r&eacute;indexation</h2>
<p>La communication avec Solr se fait via des transferts de XML en HTTP. Rien de bien complexe, mais il existe d&eacute;j&agrave; des classes toutes faites pour faciliter les choses, alors ne nous privons pas. La biblioth&egrave;que dont je parle <a href="http://code.google.com/p/solr-php-client/downloads/list">peut &ecirc;tre t&eacute;l&eacute;charg&eacute;e ici</a>.</p>
<p>Les fichiers de l&#8217;archives peuvent &ecirc;tre plac&eacute;es dans <em>/var/www/monprojet/lib/vendor/solr</em> (par exemple). Au passage, j&#8217;ai vir&eacute; tous les fichiers inutiles pour ne conserver que l&#8217;essentiel.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw3">cd</span> <span class="sy0">/</span>var<span class="sy0">/</span>www<span class="sy0">/</span>monprojet
<span class="kw2">ls</span> lib<span class="sy0">/</span>vendor<span class="sy0">/</span>solr<span class="sy0">/</span>
<span class="co0"># Document.php  Response.php  Service  Service.php</span>
symfony <span class="kw2">cc</span></pre></div></div>

<p>Nous allons appliquer une petite modif, pour permettre &agrave; la librairie d&#8217;utiliser le formatage des r&eacute;ponses en php par solr.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">vi</span> lib<span class="sy0">/</span>vendor<span class="sy0">/</span>solr<span class="sy0">/</span>Service.php</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// Modifiez ici :</span>
<span class="kw2">const</span> SOLR_VERSION <span class="sy0">=</span> <span class="st_h">'1.3'</span><span class="sy0">;</span>
<span class="co1">// et ici :</span>
<span class="kw2">const</span> SOLR_WRITER <span class="sy0">=</span> <span class="st_h">'phps'</span><span class="sy0">;</span></pre></div></div>

<p>Parfait. Passons &agrave; l&#8217;int&eacute;gration proprement dite. J&#8217;utilise Doctine pour le projet en question. Je vous donne donc le code correspondant &agrave; cet ORM, mais j&#8217;imagine que le travail d&#8217;adaptation pour faire fonctionner &ccedil;a avec Propel est assez minime.</p>
<p>Nous allons &eacute;diter les fichiers du mod&egrave;le pour activer l&#8217;indexation&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/model/doctrine/PhotoTable.class.php</span>
&nbsp;
<span class="co1">// Cette fonction renvoie une instance de connexion vers Solr</span>
<span class="kw2">public</span> <span class="kw2">function</span> getSolrService<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <span class="re0">$host</span> <span class="sy0">=</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'app_solr_host'</span><span class="sy0">,</span> <span class="st_h">'localhost'</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$port</span> <span class="sy0">=</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'app_solr_port'</span><span class="sy0">,</span> <span class="st_h">'8983'</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$url</span> <span class="sy0">=</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'app_solr_url'</span><span class="sy0">,</span> <span class="st_h">'/solr'</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$solr</span> <span class="sy0">=</span> <span class="kw2">new</span> Apache_Solr_Service<span class="br0">&#40;</span><span class="re0">$host</span><span class="sy0">,</span> <span class="re0">$port</span><span class="sy0">,</span> <span class="re0">$url</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">if</span><span class="br0">&#40;</span><span class="sy0">!</span><span class="re0">$solr</span><span class="sy0">-&gt;</span><span class="me1">ping</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
        throw <span class="kw2">new</span> Exception<span class="br0">&#40;</span><span class="st_h">'Search is not available right now.'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">return</span> <span class="re0">$solr</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// lib/model/doctrine/Photo.class.php</span>
&nbsp;
<span class="co1">// Un appel à cette fonction indexe la photo</span>
<span class="kw2">public</span> <span class="kw2">function</span> updateLuceneIndex<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <span class="re0">$solr</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getTable</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getSolrService</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$document</span> <span class="sy0">=</span> <span class="kw2">new</span> Apache_Solr_Document<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$document</span><span class="sy0">-&gt;</span><span class="me1">addField</span><span class="br0">&#40;</span><span class="st_h">'id'</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="co1">// On donne un poids plus important au titre</span>
    <span class="re0">$document</span><span class="sy0">-&gt;</span><span class="me1">addField</span><span class="br0">&#40;</span><span class="st_h">'title'</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getTitle</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="nu19">1.2</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$document</span><span class="sy0">-&gt;</span><span class="me1">addField</span><span class="br0">&#40;</span><span class="st_h">'description'</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getDescription</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="co1">// getTags() renvoie un bête tableau</span>
    <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getTags</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw1">as</span> <span class="re0">$tag</span><span class="br0">&#41;</span>
        <span class="re0">$document</span><span class="sy0">-&gt;</span><span class="me1">setMultiValue</span><span class="br0">&#40;</span><span class="st_h">'tag'</span><span class="sy0">,</span> <span class="re0">$tag</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$solr</span><span class="sy0">-&gt;</span><span class="me1">addDocument</span><span class="br0">&#40;</span><span class="re0">$document</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$solr</span><span class="sy0">-&gt;</span><span class="me1">commit</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Réindexation après une création / modification</span>
<span class="kw2">public</span> <span class="kw2">function</span> postSave<span class="br0">&#40;</span><span class="re0">$event</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">updateLuceneIndex</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Désindexation après une suppression</span>
protected <span class="kw2">function</span> postDelete<span class="br0">&#40;</span><span class="re0">$event</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <span class="re0">$solr</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getTable</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getSolrService</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$solr</span><span class="sy0">-&gt;</span><span class="me1">deleteById</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>Ins&eacute;rez / modifiez quelques photos, qui devraient s&#8217;indexer correctement. Pour le v&eacute;rifier, passons au moteur de recherche.</p>
<h2>Le moteur de recherche</h2>
<p>Il existe grosso-modo deux m&eacute;thodes&nbsp;: premi&egrave;re solution, les champs &agrave; afficher dans les r&eacute;sultats du moteur de recherche sont stock&eacute;s directement dans l&#8217;index (stored=&nbsp;&nbsp;&raquo;true&nbsp;&nbsp;&raquo; dans le schema.xml), auquel cas il vous suffit de les cracher tels quels. La deuxi&egrave;me solution, celle qui est utilis&eacute;e dans le tutoriel jobeet et que je vous pr&eacute;sente ici, consiste &agrave; utiliser solr pour r&eacute;cup&eacute;rer les ids, et &agrave; lancer une requ&ecirc;te via votre ORM derri&egrave;re.</p>
<p>J&#8217;ai choisi la deuxi&egrave;me solution car je partais d&#8217;une base existante, et je voulais modifier mon code le moins possible, mais le premier choix est certainement meilleur en terme de perfs. &Agrave; vous de voir.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// app/frontend/module/photo/actions/actions.class.php</span>
&nbsp;
<span class="kw2">public</span> <span class="kw2">function</span> executeSearch<span class="br0">&#40;</span>sfWebRequest <span class="re0">$request</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <span class="co1">// On récupère la requête soumise</span>
    <span class="co1">// Pour la syntaxe, voir là bas :</span>
    <span class="co1">// http://lucene.apache.org/java/2_3_2/queryparsersyntax.html</span>
    <span class="re0">$q</span> <span class="sy0">=</span> <span class="re0">$request</span><span class="sy0">-&gt;</span><span class="me1">getParameter</span><span class="br0">&#40;</span><span class="st_h">'q'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="co1">// À partir de cette requête, on forge un objet Doctrine_Query</span>
    <span class="re0">$query</span> <span class="sy0">=</span> Doctrine<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span><span class="st_h">'Photo'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getSearchQuery</span><span class="br0">&#40;</span><span class="re0">$q</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="co1">// Ensuite, vous en faites ce que vous voulez</span>
    <span class="co1">// De la pagination, par exemple</span>
    <span class="co1">// http://www.miximum.fr/tutos/186-la-pagination-avec-doctrine</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// lib/model/doctrine/PhotoTable.class.php</span>
<span class="kw2">public</span> <span class="kw2">function</span> getSearchQuery<span class="br0">&#40;</span><span class="re0">$queryString</span><span class="sy0">,</span> <span class="re0">$maxHits</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <span class="co1">// He ! On peut déjà limiter le nombre de résultats retournés. Cool, non ?!</span>
    <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$maxHits</span> <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span>
        <span class="re0">$maxHits</span> <span class="sy0">=</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'app_solr_max_hits'</span><span class="sy0">,</span> <span class="nu0">256</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$offset</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
    <span class="re0">$solr</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getSolrService</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$response</span> <span class="sy0">=</span> <span class="re0">$solr</span><span class="sy0">-&gt;</span><span class="me1">search</span><span class="br0">&#40;</span><span class="re0">$queryString</span><span class="sy0">,</span> <span class="re0">$offset</span><span class="sy0">,</span> <span class="re0">$maxHits</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="co1">// Solr nous renvoie directement du php, vous vous rappelez ?</span>
    <span class="re0">$response</span> <span class="sy0">=</span> <a href="http://www.php.net/unserialize"><span class="kw3">unserialize</span></a><span class="br0">&#40;</span><span class="re0">$response</span><span class="sy0">-&gt;</span><span class="me1">getRawResponse</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="co1">// On se retrouve donc avec une liste de résultas sous forme d'un tableau d'ids</span>
    <span class="re0">$pks</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$response</span><span class="br0">&#91;</span><span class="st_h">'response'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'docs'</span><span class="br0">&#93;</span> <span class="kw1">as</span> <span class="re0">$doc</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        <span class="re0">$pks</span><span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="re0">$doc</span><span class="br0">&#91;</span><span class="st_h">'id'</span><span class="br0">&#93;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="re0">$query</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">createQuery</span><span class="br0">&#40;</span><span class="st_h">'p'</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="sy0">-&gt;</span><span class="me1">select</span><span class="br0">&#40;</span><span class="st_h">'p.*'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">if</span><span class="br0">&#40;</span><a href="http://www.php.net/empty"><span class="kw3">empty</span></a><span class="br0">&#40;</span><span class="re0">$pks</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
        <span class="co1">// pas de résultat</span>
        <span class="re0">$query</span><span class="sy0">-&gt;</span><span class="me1">whereIn</span><span class="br0">&#40;</span><span class="st_h">'p.id'</span><span class="sy0">,</span> <span class="sy0">-</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw1">else</span>
    <span class="br0">&#123;</span>
        <span class="re0">$query</span><span class="sy0">-&gt;</span><span class="me1">whereIn</span><span class="br0">&#40;</span><span class="st_h">'p.id'</span><span class="sy0">,</span> <span class="re0">$pks</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="co1">// Ça, c'est pour conserver le tri par pertinence. Voir là bas :</span>
        <span class="co1">// http://groups.google.com/group/symfony-users/browse_thread/thread/92adb0332dfe1065/ee7b8c0d27208368?lnk=gst&amp;q=zend+search+sort#ee7b8c0d27208368</span>
        <span class="re0">$query</span><span class="sy0">-&gt;</span><span class="me1">addSelect</span><span class="br0">&#40;</span><span class="st_h">'FIELD(p.id,'</span> <span class="sy0">.</span> <a href="http://www.php.net/implode"><span class="kw3">implode</span></a><span class="br0">&#40;</span><span class="st_h">','</span><span class="sy0">,</span> <span class="re0">$pks</span><span class="br0">&#41;</span> <span class="sy0">.</span> <span class="st_h">') AS field'</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="re0">$query</span><span class="sy0">-&gt;</span><span class="me1">orderBy</span><span class="br0">&#40;</span><span class="st_h">'field'</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
    <span class="kw1">return</span> <span class="re0">$query</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>Et nous voil&agrave; avec un moteur viable. Libre &agrave; vous de le perfectionner &agrave; votre convenance ensuite.</p>
<h2>R&eacute;indexation compl&egrave;te du site</h2>
<div class="alignleft postimg"><a href="http://www.flickr.com/photos/58013815@N00/123832255/" title="Pipe and Chin" target="_blank"><img src="http://farm1.static.flickr.com/42/123832255_901ef03739_m.jpg" alt="Pipe and Chin" border="0" /></a><br /><small><a href="http://creativecommons.org/licenses/by-nc-sa/2.0/" title="Attribution-NonCommercial-ShareAlike License" target="_blank"><img src="http://www.miximum.fr/wp-content/plugins/photo-dropper/images/cc.png" alt="Creative Commons License" border="0" width="16" height="16" align="absmiddle" /></a> <a href="http://www.photodropper.com/photos/" target="_blank">photo</a> credit&nbsp;: <a href="http://www.flickr.com/photos/58013815@N00/123832255/" title="Dance Party Duo" target="_blank">Dance Party Duo</a></small></div>
<p>Vos documents s&#8217;indexent maintenant automatiquement, et vous disposez d&#8217;un moteur de recherche. Pour le moment, cependant, les photos pr&eacute;existentes qui n&#8217;ont pas &eacute;t&eacute; modifi&eacute;es ne sont pas r&eacute;index&eacute;es. Je vous donne donc une t&acirc;che qui vous permettra de r&eacute;soudre ce probl&egrave;me, et d&#8217;indexer d&#8217;un coup toutes les photos du site.</p>
<p>Il devrait⁻&ecirc;tre possible, normalement, d&#8217;exporter les donn&eacute;es sous forme de xml via je ne sais quel dump, pour les envoyer directement &agrave; Luc&egrave;ne. Auquel cas, l&#8217;indexation ne prendrais que quelques secondes. Perso, j&#8217;ai bricol&eacute; vite fait un truc qui parcourt tous les objets, et qui les r&eacute;indexe un par un, ce qui est beaucoup moins efficace (mais c&#8217;est fait &agrave; la va vite).</p>
<p>De plus, il est impossible, si votre base contient un grand nombre d&#8217;objet, de tous les r&eacute;cup&eacute;rer et de boucler dessus, car le garbage collector de php n&#8217;est pas encore assez puissant pour le permettre (vivement la 5.3). J&#8217;ai donc &eacute;galement un script en shell, qui lance plusieurs fois de suite la symfony task.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co0"># lib/task/reindex.sh</span>
<span class="co0">#! /bin/bash</span>
&nbsp;
<span class="co0"># on vide l'index d'abord</span>
php symfony video:reset-index <span class="re5">--env</span>=prod
&nbsp;
<span class="re2">result</span>=<span class="nu0">0</span>
<span class="re2">i</span>=<span class="nu0">0</span>
<span class="kw1">while</span> <span class="br0">&#91;</span> <span class="re1">$result</span> <span class="re5">-eq</span> <span class="nu0">0</span> <span class="br0">&#93;</span> ; <span class="kw1">do</span>
    <span class="kw3">let</span> <span class="re2">offset</span>=<span class="re1">$i</span><span class="sy0">*</span><span class="nu0">50</span>
    php symfony photo:reindex <span class="re5">--env</span>=prod <span class="nu0">50</span> <span class="re1">$offset</span>
    <span class="re2">result</span>=<span class="re4">$?</span>
    <span class="kw3">let</span> <span class="re2">i</span>=<span class="re1">$i</span>+<span class="nu0">1</span>
<span class="kw1">done</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">// lib/task/resetIndexTask.class.php</span>
<span class="co1">// ...</span>
<span class="co1">// Supprime tous les documents de l'index</span>
protected <span class="kw2">function</span> execute<span class="br0">&#40;</span><span class="re0">$arguments</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="re0">$options</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <span class="co1">// initialize the database connection</span>
    <span class="re0">$databaseManager</span> <span class="sy0">=</span> <span class="kw2">new</span> sfDatabaseManager<span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">configuration</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$connection</span> <span class="sy0">=</span> <span class="re0">$databaseManager</span><span class="sy0">-&gt;</span><span class="me1">getDatabase</span><span class="br0">&#40;</span><span class="re0">$options</span><span class="br0">&#91;</span><span class="st_h">'connection'</span><span class="br0">&#93;</span> ? <span class="re0">$options</span><span class="br0">&#91;</span><span class="st_h">'connection'</span><span class="br0">&#93;</span> <span class="sy0">:</span> <span class="kw4">null</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getConnection</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">logSection</span><span class="br0">&#40;</span><span class="st_h">'lucene'</span><span class="sy0">,</span> <span class="st_h">'Reset index'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$solr</span> <span class="sy0">=</span> Doctrine<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span><span class="st_h">'Photo'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getSolrService</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$solr</span><span class="sy0">-&gt;</span><span class="me1">deleteByQuery</span><span class="br0">&#40;</span><span class="st_h">'*:*'</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$solr</span><span class="sy0">-&gt;</span><span class="me1">commit</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// lib/task/indexTask.class.php</span>
&nbsp;
<span class="co1">// ...</span>
protected <span class="kw2">function</span> configure<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">addArguments</span><span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
                <span class="kw2">new</span> sfCommandArgument<span class="br0">&#40;</span><span class="st_h">'limit'</span><span class="sy0">,</span> sfCommandArgument<span class="sy0">::</span><span class="me2">REQUIRED</span><span class="sy0">,</span> <span class="nu0">50</span><span class="br0">&#41;</span><span class="sy0">,</span>
                <span class="kw2">new</span> sfCommandArgument<span class="br0">&#40;</span><span class="st_h">'offset'</span><span class="sy0">,</span> sfCommandArgument<span class="sy0">::</span><span class="me2">REQUIRED</span><span class="sy0">,</span> <span class="nu0">50</span><span class="br0">&#41;</span><span class="sy0">,</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="co1">// ...</span>
<span class="br0">&#125;</span>
&nbsp;
protected <span class="kw2">function</span> execute<span class="br0">&#40;</span><span class="re0">$arguments</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="re0">$options</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <span class="co1">// initialize the database connection</span>
    <span class="re0">$databaseManager</span> <span class="sy0">=</span> <span class="kw2">new</span> sfDatabaseManager<span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">configuration</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$connection</span> <span class="sy0">=</span> <span class="re0">$databaseManager</span><span class="sy0">-&gt;</span><span class="me1">getDatabase</span><span class="br0">&#40;</span><span class="re0">$options</span><span class="br0">&#91;</span><span class="st_h">'connection'</span><span class="br0">&#93;</span> ? <span class="re0">$options</span><span class="br0">&#91;</span><span class="st_h">'connection'</span><span class="br0">&#93;</span> <span class="sy0">:</span> <span class="kw4">null</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getConnection</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$nbPhotos</span> <span class="sy0">=</span>  Doctrine<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span><span class="st_h">'Photo'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">createQuery</span><span class="br0">&#40;</span><span class="st_h">'p'</span><span class="br0">&#41;</span>
        <span class="sy0">-&gt;</span><span class="me1">count</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$offset</span> <span class="sy0">=</span> <span class="re0">$arguments</span><span class="br0">&#91;</span><span class="st_h">'offset'</span><span class="br0">&#93;</span><span class="sy0">;</span>
    <span class="re0">$limit</span> <span class="sy0">=</span> <span class="re0">$arguments</span><span class="br0">&#91;</span><span class="st_h">'limit'</span><span class="br0">&#93;</span><span class="sy0">;</span>
    <span class="re0">$log</span> <span class="sy0">=</span> <a href="http://www.php.net/sprintf"><span class="kw3">sprintf</span></a><span class="br0">&#40;</span><span class="st_h">'indexing from %d to %d on %d photos'</span><span class="sy0">,</span> <span class="re0">$offset</span><span class="sy0">,</span> <span class="re0">$offset</span> <span class="sy0">+</span> <span class="re0">$limit</span><span class="sy0">,</span> <span class="re0">$nbPhotos</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">logSection</span><span class="br0">&#40;</span><span class="st_h">'lucene'</span><span class="sy0">,</span> <span class="re0">$log</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$q</span> <span class="sy0">=</span> Doctrine<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span><span class="st_h">'Photo'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">createQuery</span><span class="br0">&#40;</span><span class="st_h">'p'</span><span class="br0">&#41;</span>
        <span class="sy0">-&gt;</span><span class="me1">limit</span><span class="br0">&#40;</span><span class="re0">$limit</span><span class="br0">&#41;</span>
        <span class="sy0">-&gt;</span><span class="me1">offset</span><span class="br0">&#40;</span><span class="re0">$offset</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="re0">$photos</span> <span class="sy0">=</span> <span class="re0">$q</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$photos</span> <span class="kw1">as</span> <span class="re0">$photo</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        <span class="re0">$photo</span><span class="sy0">-&gt;</span><span class="me1">updateLuceneIndex</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="kw1">echo</span> <span class="st_h">'.'</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">printLoading</span><span class="br0">&#40;</span><span class="re0">$nbPhotos</span><span class="sy0">,</span> <span class="re0">$limit</span><span class="sy0">,</span> <span class="re0">$offset</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">return</span> <span class="br0">&#40;</span><span class="re0">$offset</span> <span class="sy0">+</span> <span class="re0">$limit</span> <span class="sy0">&lt;</span> <span class="re0">$nbPhotos</span><span class="br0">&#41;</span> ? <span class="nu0">0</span> <span class="sy0">:</span> <span class="nu0">1</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
protected <span class="kw2">function</span> printLoading<span class="br0">&#40;</span><span class="re0">$nbPhotos</span><span class="sy0">,</span> <span class="re0">$limit</span><span class="sy0">,</span> <span class="re0">$offset</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <a href="http://www.php.net/printf"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st0">&quot; <span class="es6">%.2f</span> <span class="es6">%%</span><span class="es1">\n</span>&quot;</span><span class="sy0">,</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="re0">$limit</span> <span class="sy0">+</span> <span class="re0">$offset</span><span class="br0">&#41;</span> <span class="sy0">/</span> <span class="re0">$nbPhotos</span><span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>Vous pouvez lancer la b&ecirc;te comme &ccedil;a&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="kw2">su</span> - www-data <span class="re5">-c</span> <span class="st0">&quot;cd /var/www/monprojet &amp;&amp; ./lib/task/reindex.sh&quot;</span></pre></div></div>

<h2>M&eacute;ga Bonus</h2>
<p>Pfiou<span class="fine">&nbsp;</span>! Ben voil&agrave;, &ccedil;a sera tout, me direz vous<span class="fine">&nbsp;</span>! Et bien non, messieurs dames<span class="fine">&nbsp;</span>! Car ici, on aime les lecteurs, alors on leur en donne toujours plus. En bonus, donc, voici les <strong>scripts debian de gestion du d&eacute;mon solr</strong> (pour &eacute;viter de le lancer &agrave; la main &agrave; chaque reboot)<span class="fine">&nbsp;</span>! Note&nbsp;: je les ai <a href="http://ez.no/de/developer/forum/extensions/ez_find/script_to_run_solr_as_a_service">honteusement emprunt&eacute;s au projet eZ Publish</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co0"># /etc/init.d/solr</span>
&nbsp;
<span class="co0">#! /bin/sh</span>
&nbsp;
<span class="kw1">set</span> <span class="re5">-e</span>
&nbsp;
<span class="re2">PATH</span>=<span class="sy0">/</span>usr<span class="sy0">/</span>local<span class="sy0">/</span>sbin:<span class="sy0">/</span>usr<span class="sy0">/</span>local<span class="sy0">/</span>bin:<span class="sy0">/</span>sbin:<span class="sy0">/</span>bin:<span class="sy0">/</span>usr<span class="sy0">/</span>sbin:<span class="sy0">/</span>usr<span class="sy0">/</span>bin
<span class="re2">DESC</span>=<span class="st0">&quot;Solr indexing server&quot;</span>
<span class="re2">NAME</span>=solr
<span class="re2">SOLR_HOME</span>=<span class="sy0">/</span>opt<span class="sy0">/</span>solr<span class="sy0">/</span>monprojet
<span class="re2">DAEMON</span>=<span class="re1">$SOLR_HOME</span><span class="sy0">/</span><span class="re1">$NAME</span>.sh
<span class="re2">PIDFILE</span>=<span class="sy0">/</span>var<span class="sy0">/</span>run<span class="sy0">/</span><span class="re1">$NAME</span>.pid
<span class="re2">SCRIPTNAME</span>=<span class="sy0">/</span>etc<span class="sy0">/</span>init.d<span class="sy0">/</span><span class="re1">$NAME</span>
&nbsp;
<span class="co0"># Gracefully exit if the package has been removed.</span>
<span class="kw3">test</span> <span class="re5">-x</span> <span class="re1">$DAEMON</span> <span class="sy0">||</span> <span class="kw3">exit</span> <span class="nu0">0</span>
&nbsp;
<span class="co0"># Read config file if it is present.</span>
<span class="kw1">if</span> <span class="br0">&#91;</span> <span class="re5">-r</span> <span class="sy0">/</span>etc<span class="sy0">/</span>default<span class="sy0">/</span><span class="re1">$NAME</span> <span class="br0">&#93;</span>
<span class="kw1">then</span>
    . <span class="sy0">/</span>etc<span class="sy0">/</span>default<span class="sy0">/</span><span class="re1">$NAME</span>
<span class="kw1">fi</span>
&nbsp;
<span class="co0">#</span>
<span class="co0">#   Function that starts the daemon/service.</span>
<span class="co0">#</span>
d_start<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    start-stop-daemon <span class="re5">--start</span> <span class="re5">--pidfile</span> <span class="re1">$PIDFILE</span> \
                <span class="re5">--chdir</span> <span class="re1">$SOLR_HOME</span> <span class="re5">--background</span> <span class="re5">--make-pidfile</span> \
        <span class="re5">--exec</span> <span class="re1">$DAEMON</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co0">#</span>
<span class="co0">#   Function that stops the daemon/service.</span>
<span class="co0">#</span>
d_stop<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    start-stop-daemon <span class="re5">--stop</span> <span class="re5">--quiet</span> <span class="re5">--pidfile</span> <span class="re1">$PIDFILE</span> \
        <span class="re5">--name</span> java
        <span class="kw2">rm</span> <span class="re5">-f</span> <span class="re1">$PIDFILE</span>
<span class="br0">&#125;</span>
<span class="kw1">case</span> <span class="st0">&quot;$1&quot;</span> <span class="kw1">in</span>
  start<span class="br0">&#41;</span>
    <span class="kw3">echo</span> <span class="re5">-n</span> <span class="st0">&quot;Starting <span class="es2">$DESC</span>: <span class="es2">$NAME</span>&quot;</span>
    d_start
    <span class="kw3">echo</span> <span class="st0">&quot;.&quot;</span>
    <span class="sy0">;;</span>
  stop<span class="br0">&#41;</span>
    <span class="kw3">echo</span> <span class="re5">-n</span> <span class="st0">&quot;Stopping <span class="es2">$DESC</span>: <span class="es2">$NAME</span>&quot;</span>
    d_stop
    <span class="kw3">echo</span> <span class="st0">&quot;.&quot;</span>
    <span class="sy0">;;</span>
  restart<span class="sy0">|</span>force-reload<span class="br0">&#41;</span>
    <span class="kw3">echo</span> <span class="re5">-n</span> <span class="st0">&quot;Restarting <span class="es2">$DESC</span>: <span class="es2">$NAME</span>&quot;</span>
    d_stop
    <span class="kw2">sleep</span> <span class="nu0">1</span>
    d_start
    <span class="kw3">echo</span> <span class="st0">&quot;.&quot;</span>
    <span class="sy0">;;</span>
  <span class="sy0">*</span><span class="br0">&#41;</span>
    <span class="kw3">echo</span> <span class="st0">&quot;Usage: <span class="es2">$SCRIPTNAME</span> {start|stop|restart|force-reload}&quot;</span> <span class="sy0">&gt;&amp;</span><span class="nu0">2</span>
    <span class="kw3">exit</span> <span class="nu0">1</span>
    <span class="sy0">;;</span>
<span class="kw1">esac</span>
&nbsp;
<span class="kw3">exit</span> <span class="nu0">0</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co0"># /opt/solr/monprojet/solr.sh</span>
&nbsp;
<span class="co0">#!/bin/bash</span>
&nbsp;
<span class="kw1">for</span> JAVA <span class="kw1">in</span> <span class="st0">&quot;<span class="es2">$JAVA_HOME</span>/bin/java&quot;</span> <span class="st0">&quot;/usr/bin/java&quot;</span> <span class="st0">&quot;/usr/local/bin/java&quot;</span>
<span class="kw1">do</span>
  <span class="kw1">if</span> <span class="br0">&#91;</span> <span class="re5">-x</span> <span class="re1">$JAVA</span> <span class="br0">&#93;</span>
  <span class="kw1">then</span>
    <span class="kw3">break</span>
  <span class="kw1">fi</span>
<span class="kw1">done</span>
&nbsp;
<span class="kw1">if</span> <span class="br0">&#91;</span> <span class="sy0">!</span> <span class="re5">-x</span> <span class="re1">$JAVA</span> <span class="br0">&#93;</span>
<span class="kw1">then</span>
  <span class="kw3">echo</span> <span class="st0">&quot;Unable to locate java. Please set JAVA_HOME environment variable.&quot;</span>
  <span class="kw3">exit</span>
<span class="kw1">fi</span>
&nbsp;
<span class="co0"># start solr</span>
<span class="kw3">exec</span> <span class="re1">$JAVA</span> <span class="re5">-jar</span> start.jar</pre></div></div>

<p>Et on active tout &ccedil;a par un&nbsp;:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">update-rc.d solr defaults
<span class="sy0">/</span>etc<span class="sy0">/</span>init.d<span class="sy0">/</span>solr start</pre></div></div>

<p>Ouf et re-ouf<span class="fine">&nbsp;</span>! &Ccedil;a devrait suffire pour le moment. Vous voil&agrave; maintenant avec une installation basique d&#8217;un excellent moteur de recherche, capable d&#8217;indexer des dizaines de milliers de documents, et de faire de recherches dedans avec des performances d&eacute;concertantes. Quand &agrave; moi, je vais allez me passer les doigts sous l&#8217;eau froide. &Agrave; la prochaine<span class="fine">&nbsp;</span>!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.miximum.fr/tutos/192-integrer-solr-a-symfony/feed</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
	</channel>
</rss>

