Viele werden die Funktion des autocomplete oder auto suggest z.B. von Google kennen und schätzen. Es ist doch sehr komfortabel sich die besten Begriffe vorschlagen zu lassen wenn man nicht genau weiß wonach man sucht/suchen sollte. So erspart man sich frustrierende Seiten ohne Suchergebnisse und findet vielleicht sogar noch Dinge, die man nicht auf dem Schirm hatte. Um das auch den Besuchern im eigenen Portal anbieten zu können, bietet Solr mittlerweile verschiedene Möglichkeiten, solch ein autocomplete umzusetzen.
Die suggest Komponente
Diese Komponente kann seit SOLR 3 für ein mächtiges autocomplete verwendet werden. Dafür brauchen wir lediglich einen neuen Feldtyp in der schema.xml, welcher die Informationen für das autocomplete aufbereitet. Damit ganze Phrasen unterstützt werden, könnte der Feldtyp wie folgt aussehen:
<fieldtype class="solr.TextField" name="text_autocomplete" positionincrementgap="100"> <analyzer type="index"> <tokenizer class="solr.WhitespaceTokenizerFactory"/> <filter class="solr.LowerCaseFilterFactory"/> <!-- nur Zahlen, Buchstaben und Leerzeichen um Anführungszeichen etc. zu entfernen --> <filter class="solr.PatternReplaceFilterFactory" pattern="([^a-zäöüÄÖÜß0-9 ])" replacement="" replace="all"/> <!-- Wortgruppen erstellen. Wenn wir das nicht tun, bekommen wir den kompletten Text nach einem Hit. Wenn man z.B. Text wie "the quick brown fox jumps over the lazy frog" indiziert und nach „the quick“ sucht, bekommt ohne ShingleFilter das Ergebnis "the quick brown fox jumps over the lazy frog" und mit dem ShingleFilter erhalten z.B. "the quick brown fox" --> <filter class="solr.ShingleFilterFactory" maxshinglesize="4" outputunigrams="true"/> <filter class="solr.TrimFilterFactory"/> <filter class="solr.RemoveDuplicatesTokenFilterFactory"/> </analyzer> <analyzer type="query"> <tokenizer class="solr.WhitespaceTokenizerFactory"/> <filter class="solr.LowerCaseFilterFactory"/> <filter class="solr.TrimFilterFactory"/> <filter class="solr.PatternReplaceFilterFactory" pattern="([^a-zäöüÄÖÜß0-9 ])" replacement="" replace="all"/> <filter class="solr.RemoveDuplicatesTokenFilterFactory"/> </analyzer> </fieldtype>
Dieser Feldtyp muss dann einfach für ein neues Feld vergeben werden, in welches per copyField die gewünschten Felder/Informationen eingefügt werden:
<field name="text_autocomplete_phrases" type="text_autocomplete" indexed="true" stored="false" multivalued="true"/> <copyfield source="title" dest="text_autocomplete_phrases"/>
Zuletzt benötigen wir noch einen requestHandler, der uns die Vorschläge liefert:
<requesthandler name="/suggest" class="org.apache.solr.handler.component.SearchHandler"> <lst name="defaults"> <str name="spellcheck">true</str> <str name="spellcheck.dictionary">suggest_fst</str> <str name="spellcheck.count">10</str> <!-- wenn das false ist, werden Ergebnisse nach den Buchstaben sortiert und nicht nach dem score/weight. --> <str name="spellcheck.onlyMorePopular">true</str> </lst> <!-- search component registrieren --> <arr name="components"> <str>suggest_fst</str> </arr> </requesthandler> <queryconverter name="queryConverter" class="org.dmk.solr4.spelling.MultiWordSpellingQueryConverter"> <searchcomponent name="suggest_fst" class="solr.SpellCheckComponent"> <lst name="spellchecker"> <!-- Ab Solr 4.1.x sollte die AnalyzingLookupFactory getestet werden da diese case sensitive Vorschläge liefert. @see http://lucene.apache.org/core/4_4_0/suggest/org/apache/lucene/search/suggest/analyzing/AnalyzingSuggester.html @see http://www.norconex.com/serving-autocomplete-suggestions-fast/ @see http://svn.apache.org/repos/asf/lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/solrconfig-phrasesuggest.xml <str name="lookupImpl">org.apache.solr.spelling.suggest.fst.AnalyzingLookupFactory</str> --> <str name="name">suggest_fst</str> <!-- das Feld für index building. Sollte alle Informationen für Vorschläge enthalten --> <str name="field">text_autocomplete_phrases</str> <str name="classname">org.apache.solr.spelling.suggest.Suggester</str> <!-- wenig Speicherverbrauch und schnell --> <str name="lookupImpl">org.apache.solr.spelling.suggest.fst.FSTLookup</str> <!-- das Verzeichnis im data Ordner, welches den index enthält. --> <str name="storeDir">suggest_fst</str> <str name="buildOnOptimize">true</str> <bool name="exactMatchFirst">true</bool> <int name="weightBuckets">100</int> </lst> </searchcomponent>
Warum ein eigener query converter?
Von Haus aus parsed Solr 3.x und älter die Query, welche an die Suggest-Komponente gegeben wird, mit einem Whitespace Tokenizer. Es gibt auch keine Möglichkeit dieses Verhalten zu unterbinden. So gibt es bei der Eingabe von mehreren Wörtern Vorschläge für jedes einzelne Wort, aber nicht für die gesamte Wortgruppe im Stück. Es gibt allerdings die Möglichkeit einen eigenen Query Converter anzugegeben.
Unsere TYPO3 Extension MKSEARCH liefert den Query Conferier org.dmk.solr.spelling.MultiWordSpellingQueryConverter bzw. org.dmk.solr4.spelling.MultiWordSpellingQueryConverter. Damit Solr diesen findet, muss die .jar-Datei EXT:mksearch/solr/lib/dmk-solr-core-3.5.0.jar bzw. EXT:mksearch/solr/lib/Dmk-MultiWordSpellingQueryConverter-Solr4.jar in den Ordner $SOLRHOME/lib kopiert/verlinkt werden. Wo das $SOLRHOME ist, lässt sich z.B. in der Solr-Management-Konsole auslesen. Entweder ist das der Ordner, der die solr.xml enthält oder es ist der jeweilige Core-Ordner (z.B. $SOLRHOME/$COREHOME/lib). Wenn die .jar Datei am falschen Ort liegt, wird diese nicht automatisch von Solr gefunden und es gibt einen Fehler. Der Ordner muss ggf. angelegt werden. Anschließend werden ganze Wortgruppen unterstützt. Wie groß diese Wortgruppen sind, hängt von der Konfiguration des Shingle Filters im Feldtyp ab.
Wenn Sie die Suggest-Komponente nachträglich integrieren, müssen Sie unbedingt eine Neuindizierung aller Daten vornehmen!
Autocomplete in TYPO3
Unsere TYPO3 Extension MKSEARCH bietet ein autocomplete Feature, welches über die TS Konfiguration plugin.tx_mksearch.searchsolr.autocomplete.enable aktiviert werden kann. Über plugin.tx_mksearch.searchsolr.autocomplete.elementSelector kann der jQuery Element Selektor angegeben werden, welchem die autocomplete Liste angehangen werden soll. Damit autocomplete funktioniert, registriert mksearch einen eigenen Seitentyp (540) auf welchem sich ein mksearch-Plugin befindet.
Der Standard Query Type ist “/suggest”. Dieser kann aber geändert werden über lib.mksearchAjaxPage.searchsolr.requestHandler=/suggest
Nun muss noch Solr für autocomplete vorbereitet werden wie weiter oben beschrieben. Sowohl für das schema.xml als auch für solrconfig.xml lassen sich Beispiele in den mitgelieferten XMLs (EXT:mksearch/solr/conf/) finden.