Dokumentation REDAXO
Addon XSearch
- Zu dieser Dokumentation
- Allgemein/Voraussetzungen
- Funktionen/Merkmale
- Installation
- Konfiguration
- Einsatz
- Beispiel: Einfaches Sucheingabemodul
- Beispiel: Einfaches Beispielmodul
- Beispiel: Erweitertes Beispielmodul
- Beispiel: Suche in einer bestimmten Kategorie/bestimmten Artikeln
- Beispiel: Bildersuche
- Beispiel: Suche mit Pagination
- Beispiel: Ähnlichkeitssuche
- Beispiel: Suche mit PDF-Dateien, Pagination und Ähnlichkeitssuche
- Beispiel: Komplexe Suche
- Plugins
- Rückgabe / Ergebnisarray
- Funktionsweise
- Die Klasse XSearch
- Tipps, Tricks und FAQ
- Die automatische Indexierung funktioniert nicht für meine ausgewählten Datenbankspalten. Was kann ich tun?
- Wörter mit Umlauten und Sonderzeichen werden bei der Suche nicht gefunden. Warum ist das so und wie kann ich das beheben?
- Ich komme mit der Installation nicht zurecht. Gibt es eine Schritt-für-Schritt-Anleitung?
- Wie kann ich sprachabhängig suchen?
- Ich habe ein Problem, was hier nicht behandelt wird. Wo kann ich nachfragen?
Zu dieser Dokumentation
Diese Wikiseite erklärt die Konfiguration des Addons, die Schnittstelle der XSearch-Klasse und zeigt anhand von Beispielen, wie Suchmodule aufgebaut werden können.
Allgemein/Voraussetzungen
Das Addon XSearch fügt Redaxo eine Volltextsuche hinzu.
Dabei werden Artikel und auswählbare Datenbankspalten in einer DB-Tabelle des Addons gespeichert.
Suchanfragen können außerdem in einer Cache-Tabelle gespeichert werden. Das spart Serverrechenleistung und führt zur schnelleren Anzeige von Suchergebnissen.
Das Addon setzt PHP >= 4, "MySQL >= 4.1" und Redaxo >= 4.2 voraus.
Funktionen/Merkmale
- Volltextsuche für Artikel und beliebige Datenbankspalten
- mehrsprachenfähig
- Suche im Originaltext, im Plaintext oder in beiden möglich
- Suchmodi: OR (mindestens ein Suchwort muss enthalten sein) und AND (alle Suchworte müssen enthalten sein)
- Suche mit LIKE oder MATCH AGAINST
- Verschiedene Möglichkeiten Suchwörter hervorzuheben
- Einstellen einer maximalen Trefferanzahl
- Einstellen der maximalen Zeichenanzahl für den Teaser-Text
- automatisches (De)Indexieren von Artikeln und Spalten soweit möglich
- Caching von Suchanfragen
- Eingabe von Blacklistwörtern
- Ausschluss von Artikeln oder Kategorien möglich
- Ähnliche Wörter werden von der Suche automatisch vorgeschlagen
- Suchbegriffe können mit Anführungszeichen (") umschlossen werden
- Suchbegriffe können mit einer beliebigen Anzahl von vorangestellten Pluszeichen (+) höher gewichtet werden (wirkt sich auf die Reihenfolge der Ergebnisse aus)
- zwei verschieden Arten, um den Suchindex zu erneuern (wenn es Probleme mit der max_execution_time gibt)
- für Entwickler interessant: über die Methoden der XSearch-Klasse kann die Suche verfeinert bzw. für mehrere Module unterschiedlich angepasst werden, außerdem ist z. B. eine Pagination von Suchergebnissen möglich
- Angabe von Kategorien, Artikeln und DB-Spalten, in denen gesucht werden soll
- Durchsuchen von beliebigen Ordnern mit beliebigen Dateien möglich
- einfache Konfiguration im Backend
- einstellbar, wer das Addon konfigurieren darf
Installation
Zur Installation des Addons muss sich der Ordner xsearch im Addon-Ordner von Redaxo befinden.
Über das Backend kann das Addon dann installiert und aktiviert werden.
Das Addon legt dabei 4 Datenbanktabellen an: Eine für die Indexierung von Artikeln und DB-Spalten, zwei für den Suchcache und eine für die Ähnlichkeitssuche.
Nach der Installation muss der Index einmal vollständig oder schrittweise erstellt werden.
Konfiguration
Backend-Ansicht:


- Logischer Suchmodus: Sie können hier den logischen Suchmodes bestimmen. Dies wirkt sich auf die Suche nach mehreren Worten aus.
- Konjunktive Suche (AND): Alle Wörter müssen im zu durchsuchenden Text enthalten sein.
- Disjunktive Suche (OR): Mindestens ein Wort muss im zu durchsuchenden Text enthalten sein.
- Textmodus: Der Textmodus bestimmt, welche Texte durchsucht werden sollen.
- Durchsuche Text ohne HTML-Tags (Plain)
- Durchsuche Text mit HTML-Tags (HTML)
- Durchsuche beides (HTML und Plain)
- Ähnlichkeitssuche
- Deaktivieren
- Soundex
- Metaphone
- Kölner Phonetik
- Alle
- MySQL-Suchmodus
- LIKE (findet auch Teilwörter, aber langsamer)
- MATCH AGAINST (findet nur ganze Wörter, schneller)
Obwohl die genauere Suche mit MATCH AGAINST weniger Suchergebnisse präsentiert, wird der Einsatz dieser Methode empfohlen, da die Suche dadurch beschleunigt wird. Das Manko der genaueren Suche - wenn man es denn so empfindet - kann leicht über die Ähnlichkeitssuche ausgeglichen werden.

- Art der Indexierung
- Indexierung der Artikel über eine HTTP-GET-Anfrage
- Indexierung der Artikel über den Redaxo-Cache (ohne Template, nur der Artikel)
- Indexierung der Artikel über den Redaxo-Cache (mit Template, liefert das gleiche Ergebnis wie per HTTP-GET-Anfrage)
- Offline-Artikel indexieren?
- Artikel (ADD, EDIT, DELETE) automatisch (de)indexieren

- Start-Tag
- End-Tag
- Maximale Trefferanzahl
- Maximale Zeichenanzahl für Teaser
- Maximale Zeichenanzahl um hervorgehobene Suchbegriffe herum
- Erscheinungsbild des Highlight-Texts
- ab Anfang des Satzes, in dem mindestens einer der Suchbegriffe auftaucht
- ab Anfang des Absatzes, in dem mindestens einer der Suchbegriffe
- alle gefundenen Suchbegriffe werden mit den sie umgebenden Wörtern dargestellt
- für jeden gefundenen Suchbegriff wird genau eine Textstelle wiedergegeben
- als Teaser, in dem eventuell vorkommende Suchbegriffe hervorgehoben sind
- als Array mit allen Suchbegriffen und Textstellen

- Wörter: Ein Liste von Wörtern, nach denen nicht gesucht werden kann/darf bzw. die keine Suchergebnisse produzieren.
- Kategorien: Hier können alle Kategorien ausgewählt werden, die nicht durchsucht werden sollen.
- Artikel: Hier können alle Artikel ausgewählt werden, die nicht durchsucht werden sollen.

- <table>.<column>: Es können DB-Spalten ausgewählt werden, die auch durchsucht werden sollen. Hierfür bietet sich z. B. die Spalte article.art_description des Addons Metainfo an.

- Dateiendungen
- Medienpool indexieren
- Verzeichnistiefe: Gibt an bis zu welcher Tiefe Dateien in den ausgewählten Verzeichnissen indexiert werden sollen.
- Folgende Ordner in die Suche einschließen: Wählen Sie die Ordner und Unterordner aus, die indexiert werden sollen. Javascript muss aktiviert sein.
Einsatz
Es werden ein paar Beispielmodule gezeigt und erklärt. Alle Module erwarten den REQUEST-Parameter (also über GET oder POST) xsearch.
Einfaches Sucheingabemodul
Dieses Suchformular muss im gleichen Artikel wie das Modul, das die Suchergebnisse ausgibt, eingebunden werden. Wenn dies nicht der Fall sein soll und das Formular z. B. im Template eingebunden wird, muss die Artikel-ID manuell so angepasst werden, dass sie auf den Artikel verweist, der die Suchergebnisse präsentiert.
<form id="xsearch_form" action="index.php" method="get">
<fieldset><legend>Suche</legend>
<input type="hidden" name="article_id" value="REX_ARTICLE_ID" />
<input type="hidden" name="clang" value="REX_CLANG_ID" />
<input type="text" name="xsearch" value="<?php if(!empty($_GET['xsearch'])) echo htmlspecialchars($_GET['xsearch']); ?>" />
</fieldset>
</form>
Einfaches Beispielmodul
Dieses Suchmodul nimmt einen Suchbegriff entgegen und gibt gefundene Artikel aus. Dabei wird von den Standardeinstellungen des Addons ausgegangen.
<?php
if(!empty($_REQUEST['xsearch']))
{
$xsearch = new XSearch();
$result = $xsearch->search($_REQUEST['xsearch']);
if($result['count'] > 0)
{
echo '<ul class="searchresults">';
foreach($result['hits'] as $hit)
{
if($hit['type'] == 'article')
{
$article = OOArticle::getArticleById($hit['fid']);
echo '<li>
<h4><a href="'.($url = htmlspecialchars($article->getUrl())).'">'.$article->getName().'</a></h4>
<p class="highlightedtext">'.$hit['highlightedtext'].'</p>
<p class="url">'.$REX['SERVER'].rex_getUrl($hit['fid'], $hit['clang']).'</p></li>';
}
}
echo '</ul>';
}
}
?>
Erweitertes Beispielmodul
Dieses Suchmodul bezieht weitere DB-Spalten in die Suche ein. Dafür müssen im Backend in der Konfiguration des Addons folgende DB-Spalten ausgewählt werden:
- PREFIX_article.name
- PREFIX_article.art_description
- PREFIX_article.art_keywords
Außerdem sollte das maximale Trefferlimit auf 20 gestellt werden.
<?php
if(!empty($_REQUEST['xsearch']))
{
$xsearch = new XSearch();
$result = $xsearch->search($_REQUEST['xsearch']);
if($result['count'] > 0)
{
echo '<ul class="searchresults">';
$ids = array();
foreach($result['hits'] as $hit)
{
if(!in_array($hit['fid'], $ids))
{
$article = OOArticle::getArticleById($hit['fid']);
if($hit['type'] == 'db_column' AND $hit['table'] == $REX['TABLE_PREFIX'].'article')
$text = $hit['article_teaser'];
else
$text = $hit['highlightedtext'];
$ids[] = $hit['fid'];
echo '<li>
<h4><a href="'.($url = htmlspecialchars($article->getUrl())).'">'.$article->getName().'</a></h4>
<p class="highlightedtext">'.$text.'</p>
<p class="url">'.$REX['SERVER'].rex_getUrl($hit['fid'], $hit['clang']).'</p></li>';
}
if(count($ids) >= 10)
break;
}
echo '</ul>';
}
}
?>
Suche in einer bestimmten Kategorie/bestimmten Artikeln
Dieses Suchmodul ist wie das erste, einfache Suchmodul aufgebaut. Einzig die Kategorien, in denen ausschließlich gesucht werden soll, sind zusätzlich angegeben.
<?php
if(!empty($_REQUEST['xsearch']))
{
$xsearch = new XSearch();
$xsearch->searchInCategories(array(5,6,13));
$result = $xsearch->search($_REQUEST['xsearch']);
if($result['count'] > 0)
{
echo '<ul class="searchresults">';
foreach($result['hits'] as $hit)
{
if($hit['type'] == 'article')
{
$article = OOArticle::getArticleById($hit['fid']);
echo '<li>
<h4><a href="'.($url = htmlspecialchars($article->getUrl())).'">'.$article->getName().'</a></h4>
<p class="highlightedtext">'.$hit['highlightedtext'].'</p>
<p class="url">'.$REX['SERVER'].rex_getUrl($hit['fid'], $hit['clang']).'</p></li>';
}
}
echo '</ul>';
}
}
?>
Bildersuche
Eine Bildersuche kann mit XSearch einfach realisiert werden.
Die Suche zu den Bildern soll in den Bildbeschreibungen und -titeln, die über den Medienpool eingetragen werden, stattfinden.
Dafür werden im Backend folgende Spalten in die Indexierung eingeschlossen:
- PREFIX_file.title
- PREFIX_file.med_description
<?php
- if(!empty($_REQUEST['xsearch']))
{
$xsearch = new XSearch();
$xsearch->searchInDbColumn($REX['TABLE_PREFIX'].'file','title');
$xsearch->searchInDbColumn($REX['TABLE_PREFIX'].'file','med_description');
$result = $xsearch->search($_REQUEST['xsearch']);
if($result['count'] > 0)
{
echo '<ul class="searchresults">';
foreach($result['hits'] as $hit)
{
$media = OOMedia::getMediaById($hit['fid']);
echo '<li>
<h4>'.$media->getTitle().'</h4>
<p class="image"><a href="'.($url = htmlspecialchars($media->getFullPath())).'"><img src="index.php?rex_resize=100a__'.$media->getFileName().'" alt="'.$media->getTitle().'" /></a></p></li>';
}
echo '</ul>';
}
}
?>
Suche mit Pagination
Für umfangreiche Webauftritte kann eine Pagination für die Suchergebnisse sinnvoll oder notwendig sein.
Diese Beispielmodul benötigt die DB-Spalten name, art_description und art_keywords aus der Tabelle rex_article.
Über die Konstante SHOWMAX kann die maximale Anzahl an Treffern, die auf der Seite angezeigt werden sollen, eingestellt werden.
<?php
define('SHOWMAX',10);
if(!empty($_REQUEST['xsearch']))
{
$xsearch = new XSearch();
$xsearch->setLimit(array($start = isset($_GET['start'])?intval($_GET['start']):0, SHOWMAX));
$xsearch->doSearchArticles(true);
$xsearch->searchInDbColumn($REX['TABLE_PREFIX'].'article', 'name');
$xsearch->searchInDbColumn($REX['TABLE_PREFIX'].'article', 'art_description');
$xsearch->searchInDbColumn($REX['TABLE_PREFIX'].'article', 'art_keywords');
$result = $xsearch->search($_REQUEST['xsearch']);
if(count($result['simwords']) > 0)
{
$newsearchString = $result['simwordsnewsearch'];
$result = $xsearch->search($newsearchString);
if($result['count'] > 0)
echo '<p>Meinten Sie <strong>'.$newsearchString.'</strong>?</p>';
}
if($result['count'] > 0)
{
echo '<ul class="searchresults">';
foreach($result['hits'] as $hit)
{
$article = OOArticle::getArticleById($hit['fid']);
if($hit['type'] == 'db_column')
$text = $hit['article_teaser'];
else
$text = $hit['highlightedtext'];
echo '<li>
<h4><a href="'.($url = htmlspecialchars($article->getUrl())).'">'.$article->getName().'</a></h4>
<p class="highlightedtext">'.$text.'</p>
<p class="url">'.$REX['SERVER'].rex_getUrl($hit['fid'], $hit['clang']).'</p></li>';
}
echo '</ul>';
// Pagination
if($result['count'] > SHOWMAX)
{
$self = OOArticle::getArticleById(REX_ARTICLE_ID);
echo '<ul class="pagination">';
for($i = 0; ($i*SHOWMAX) < $result['count']; $i++)
{
if(($i*SHOWMAX) == $start)
echo '<li>'.($i+1).'</li>';
else
echo '<li><a href="'.$self->getUrl(array('xsearch' => $_REQUEST['xsearch'], 'start' => $i*SHOWMAX)).'">'.($i+1).'</a></li>';
}
echo '</ul>';
}
}
}
?>
Ähnlichkeitssuche
Dieses Beispielmodul erweitert das Paginationsmodul um eine Suche nach ähnlichen Wörtern. Wichtig ist dabei, dass die Ähnlichkeitssuche im Backend aktiviert ist.
<?php
define('SHOWMAX',10);
if(!empty($_REQUEST['xsearch']))
{
$xsearch = new XSearch();
$xsearch->setLimit(array($start = isset($_GET['start'])?intval($_GET['start']):0, SHOWMAX));
$result = $xsearch->search($_REQUEST['xsearch']);
if(count($result['simwords']) > 0)
{
$newsearchString = $result['simwordsnewsearch'];
$result = $xsearch->search($newsearchString);
if($result['count'] > 0)
echo '<p>Meinten Sie <strong>'.$newsearchString.'</strong>?</p>';
}
if($result['count'] > 0)
{
echo '<ul class="searchresults">';
foreach($result['hits'] as $hit)
{
$article = OOArticle::getArticleById($hit['fid']);
if($hit['type'] == 'db_column')
$text = $hit['article_teaser'];
else
$text = $hit['highlightedtext'];
echo '<li>
<h4><a href="'.($url = htmlspecialchars($article->getUrl())).'">'.$article->getName().'</a></h4>
<p class="highlightedtext">'.$text.'</p>
<p class="url">'.$REX['SERVER'].rex_getUrl($hit['fid'], $hit['clang']).'</p></li>';
}
echo '</ul>';
// Pagination
if($result['count'] > SHOWMAX)
{
$self = OOArticle::getArticleById(REX_ARTICLE_ID);
echo '<ul class="pagination">';
for($i = 0; ($i*SHOWMAX) < $result['count']; $i++)
{
if(($i*SHOWMAX) == $start)
echo '<li>'.($i+1).'</li>';
else
echo '<li><a href="'.$self->getUrl(array('xsearch' => $_REQUEST['xsearch'], 'start' => $i*SHOWMAX)).'">'.($i+1).'</a></li>';
}
echo '</ul>';
}
}
else
{
echo '<em>Leider nichts gefunden.</em>';
}
}
?>
Suche mit PDF-Dateien, Pagination und Ähnlichkeitssuche
Dieses Beispielmodul erweitert das Paginationsmodul und die Ähnlichkeitssuche um die Suche von PDF-Dateien aus dem Medienpool. Die Ähnlichkeitssuche sollte aktiviert, sowie bei der Dateisuche die Option "Medienpool indexieren" ausgewählt sein. Außerdem sollte in dem Feld für die Dateiendungen nur "pdf" stehen.
<?php
define('SHOWMAX',10);
if(!empty($_REQUEST['xsearch']))
{
$xsearch = new XSearch();
$xsearch->setLimit(array($start = isset($_GET['start'])?intval($_GET['start']):0, SHOWMAX));
$result = $xsearch->search($_REQUEST['xsearch']);
if(count($result['simwords']) > 0)
{
$newsearchString = $result['simwordsnewsearch'];
$result = $xsearch->search($newsearchString);
if($result['count'] > 0)
echo '<p>Meinten Sie <strong>'.$newsearchString.'</strong>?</p>';
}
if($result['count'] > 0)
{
echo '<ul class="searchresults">';
foreach($result['hits'] as $hit)
{
if($hit['type'] == 'db_column')
$text = $hit['article_teaser'];
else
$text = $hit['highlightedtext'];
if($hit['type'] == 'file' AND $hit['fileext'] == 'pdf')
{
// PDF-Datei
$filename = explode('/', $hit['filename']);
$pdf = OOMedia::getMediaByFileName($filename[count($filename)-1]);
echo ' <li class="pdf">
<h4><a href="'.htmlspecialchars($pdf->getFullPath()).'">'.$pdf->getOrgFileName().'</a></h4>
<p class="highlightedtext">'.$text.'</p>
<p class="url">'.$REX['SERVER'].'files/'.$pdf->getOrgFileName().'</p>
</li>';
}
else
{
// Artikel oder DB-Spalte aus der Artikel-Tabelle
$article = OOArticle::getArticleById($hit['fid']);
echo ' <li>
<h4><a href="'.htmlspecialchars($article->getUrl()).'">'.$article->getName().'</a></h4>
<p class="highlightedtext">'.$text.'</p>
<p class="url">'.$REX['SERVER'].rex_getUrl($hit['fid'], $hit['clang']).'</p>
</li>';
}
}
echo '</ul>';
// Pagination
if($result['count'] > SHOWMAX)
{
$self = OOArticle::getArticleById(REX_ARTICLE_ID);
echo '<ul class="pagination">';
for($i = 0; ($i*SHOWMAX) < $result['count']; $i++)
{
if(($i*SHOWMAX) == $start)
echo '<li>'.($i+1).'</li>';
else
echo '<li><a href="'.$self->getUrl(array('xsearch' => $_REQUEST['xsearch'], 'start' => $i*SHOWMAX)).'">'.($i+1).'</a></li>';
}
echo '</ul>';
}
}
else
{
echo '<em>Leider nichts gefunden.</em>';
}
}
?>
Komplexe Suche
Dieses Beispielmodul ähnelt dem Beispiel: Modul zur Suche mit PDF-Dateien, Pagination und Ähnlichkeitssuche. Die Ähnlichkeitssuche sollte aktiviert, sowie bei der Dateisuche die Option "Medienpool indexieren" ausgewählt sein. Außerdem sollte in dem Feld für die Dateiendungen nur "pdf" stehen.
Ein erweitertes Suchformular bietet dem Nutzer an, folgende Punkte auszuwählen:
- Suchmodus (AND oder OR)
- Suchen in (Kategorieauswahl)
- Wieviele Ergebnisse pro Seite?
Wichtig: Dieses Modul ist nur für XSearch ab Version 0.5.
<form id="search-form" method="get" action="<?php echo rex_geturl(REX_ARTICLE_ID, REX_CLANG_ID, array(), '&'); ?>">
<fieldset>
<legend>Suchformular</legend>
<input type="hidden" name="article_id" value="REX_ARTICLE_ID" />
<input type="hidden" name="clang" value="REX_CLANG_ID" />
<p><label for="searchterm">Suchbegriff:</label>
<input type="text" id="searchterm" name="searchterm" value="<?php echo htmlspecialchars(rex_request('searchterm', 'string', '')); ?>" /></p>
<p><label for="logicalmode">Suchmodus:</label>
<select id="logicalmode" name="logicalmode">
<option value="and"<?php if(rex_request('logicalmode', 'string', 'and') == 'and') echo ' selected="selected"'; ?>>Suchergebnis muss alle Wörter enthalten</option>
<option value="or"<?php if(rex_request('logicalmode', 'string', 'and') == 'or') echo ' selected="selected"'; ?>>Suchergebnis muss mindestens ein Wort enthalten</option>
</select></p>
<p><label for="searchin">Suchen in:</label>
<?php $cat_select = new rex_category_select(true, REX_CLANG_ID, false, false); $cat_select->setAttribute('id', 'searchin'); $cat_select->setAttribute('name', 'searchin[]'); $cat_select->setAttribute('multiple', 'multiple'); $cat_select->setAttribute('size', '10'); $cat_select->setSelected(rex_request('searchin', 'array', array())); $cat_select->show(); ?></p>
<p><input type="checkbox" value="1" name="subcats" id="subcats"<?php if(rex_request('subcats', 'int', 0)) echo ' checked="checked"'; ?> /><label for="subcats">Unterkategorien in die Suche einschließen</label></p>
<p><label for="resultcount">Ergebnisse pro Seite:</label>
<select id="resultcount" name="resultcount">
<?php $resultcount = rex_request('resultcount', 'int', 10); foreach(array(10,20,50,100) as $option)
echo ' <option value="'.$option.'"'.($resultcount==$option?' selected="selected"':'').'>'.$option.'</option>'."\n";
?>
</select></p>
<p><input type="submit" id="submit" value="Suche starten" /></p>
</fieldset>
</form>
In dem Modul zur Präsentation der Suchergebnisse werden die entsprechenden Einstellungen an XSearch übergeben, die Suche ausgeführt und letztendlich die Suchergebnisse ausgegeben.
<?php
$searchterm = rex_request('searchterm', 'string', '');
$logicalmode = rex_request('logicalmode', 'string', 'and');
$showmax = rex_request('resultcount', 'int', 10);
$searchinIDs = rex_request('searchin', 'array', array());
$traverseSubcats = rex_request('subcats', 'bool', false);
if(!empty($searchterm))
{
$xsearch = new XSearch();
$xsearch->setLimit(array($start = rex_get('start', 'int', 0), $showmax));
$xsearch->setLogicalMode($logicalmode);
if($traverseSubcats)
$xsearch->searchInCategories(a587_getCategories(true, true, $searchinIDs));
else
{
$xsearch->searchInCategories($searchinIDs);
}
$result = $xsearch->search($searchterm);
if(count($result['simwords']) > 0)
{
$newsearchString = $result['simwordsnewsearch'];
$result = $xsearch->search($newsearchString);
if($result['count'] > 0)
echo '<p>Meinten Sie <strong>'.$newsearchString.'</strong>?</p>';
}
if($result['count'] > 0)
{
echo '<ul class="searchresults">';
foreach($result['hits'] as $hit)
{
switch($hit['type'])
{
case 'file':
$text = $hit['highlightedtext'];
// PDF-Datei
$filename = explode('/', $hit['filename']);
$pdf = OOMedia::getMediaByFileName($filename[count($filename)-1]);
echo ' <li class="pdf">
<h4><a href="'.htmlspecialchars($pdf->getFullPath()).'">'.$pdf->getOrgFileName().'</a></h4>
<p class="highlightedtext">'.$text.'</p>
<p class="url">'.$REX['SERVER'].'files/'.$pdf->getOrgFileName().'</p>
</li>';
break;
case 'db_column':
case 'article':
if($hit['type'] == 'db_column')
$text = $hit['article_teaser'];
else
$text = $hit['highlightedtext'];
// Artikel oder DB-Spalte aus der Artikel-Tabelle
$article = OOArticle::getArticleById($hit['fid']);
echo ' <li>
<h4><a href="'.htmlspecialchars($article->getUrl()).'">'.$article->getName().'</a></h4>
<p class="highlightedtext">'.$text.'</p>
<p class="url">'.$REX['SERVER'].rex_getUrl($hit['fid'], $hit['clang']).'</p>
</li>';
break;
}
}
echo '</ul>';
// Pagination
if($result['count'] > $showmax)
{
$self = OOArticle::getArticleById(REX_ARTICLE_ID);
echo '<ul class="pagination">';
for($i = 0; ($i*$showmax) < $result['count']; $i++)
{
if(($i*$showmax) == $start)
echo '<li>'.($i+1).'</li>';
else
echo '<li><a href="'.$self->getUrl(array('xsearch' => $_REQUEST['xsearch'], 'start' => $i*$showmax)).'">'.($i+1).'</a></li>';
}
echo '</ul>';
}
}
else
{
echo '<em>Leider nichts gefunden.</em>';
}
}
?>
Plugins
Installation von Plugins
Um Plugins in XSearch zu installieren ist folgendes zu tun:
- Plugin herunterladen
- Datei entpacken
- Ordner (zum Beispiel "stats") in den XSearch Unterordner plugins verschieben
- Nun erscheint im Backend unter dem XSearch Addon das neu eingefügte Plugin und kann installiert und aktiviert werden
Rückgabe / Ergebnisarray
Das Ergebnisarray, das von der search-Methode zurückgegeben wird, hat folgenden Aufbau:
- hits: ein Array der Treffer, wobei jeder Treffer selbst ein Array mit folgendem Inhalt ist:
- id: die ID des Suchergebnis´ in der Tabelle searchindex
- fid: die Fremd-ID, von dem Datensatz, der indexiert wurde (z. B. die Artikel-ID)
- table: die DB-Tabelle, von der indexiert wurde
- column: die DB-Spalte, von der indexiert wurde (NULL, wenn es ein indexierter Artikel ist)
- type: db_column oder article
- clang: Sprache
- fileext: Dateiendung
- filename: Pfad mit Dateiname
- unchangedtext: der unveränderte Originaltext
- plaintext: der von HTML- und PHP-Tags befreite Text
- teaser: Teaser (Plaintext gekürzt auf die Anzahl der maximalen Teaserzeichen)
- highlightedtext: Text oder Array mit hervorgehobenen Suchbegriffen innerhalb von Textstellen
- article_teaser: wenn ein Datenbankspalte aus der Tabelle rex_article indexiert wurde, dann steht hier der Teaser des Artikels
- keywords: Array mit allen Suchbegriffen
- searchterm: der eingegebene Suchterm
- sql: die genutzte SQL-Abfrage
- blacklisted: Array mit "schwarzen" Wörtern, die in der Suchabfrage genutzt wurden
- time: Dauer der Suche
- count: Anzahl aller Datensätze, die ohne LIMIT-Klausel gefunden werden könnten
- hash: Hash, unter dem die Suche im Cache gespeichert wurde
- simwordsnewsearch: Vorschlag für ähnliche Suchbegriffe (nur, wenn die Suche kein Ergebnis brachte)
- simwords: ein Array mit Wörtern, die den Suchbegriffen ähneln, wobei die Schlüssel dieses Arrays die eingegebenen "falschen" Wörter sind und die Werte wiederum ein Array, das wie folgt aufgebaut ist:
- typedin: noch einmal das "falsche" Wort
- keyword: das "richtige" Schlüsselwort
- count: Anzahl, wie oft das "richtige" Schlüsselwort gefunden wurde
Funktionsweise
Automatische Indexierung / Indexerneuerung
Eine Automatisch De-(Indexierung) erfolgt im Moment mit folgenden Extension-Points:
- ART_DELETED: Wenn ein Artikel gelöscht wird, fliegt er aus dem Suchcache.
- ART_META_UPDATED: Wenn Metainfos geändert wurden, werden alle ausgewählten DB-Spalten aus der Tabelle rex_article neu indexiert.
- ART_STATUS: Ein Artikel, der offline geschaltet wird, wird deindexiert, bei online indexiert.
- ART_UPDATED: wie ART_META_INFO
- CAT_DELETED: Ausgabe einer Meldung, das der Index erneuert werden muss
- CAT_STATUS: Eine Kategorie, die offline geschaltet wird, wird deindexiert, bei online indexiert.
- CAT_UPDATED: wie ART_META_INFO
- MEDIA_ADDED: Wenn ein Medium hinzugefügt wurde, werden alle ausgewählten DB-Spalten aus der Tabelle rex_file neu indexiert.
- MEDIA_UPDATED: wie MEDIA_ADDED
- SLICE_SHOW: Wichtigster Extensionpoint: Wird ein Artikel verändert (z. B. Inhalt geändert, Slice verschoben, etc...), wird er neu indexiert.
Ähnlichkeitssuche
Die Ähnlichkeitssuche muss im Backend in der Konfigurationsansicht von XSearch eingestellt werden.
Ist die Ähnlichkeitssuche aktiviert, baut XSearch bei jeder Suche, die einen Treffer ergab, einen Schlagwortindex aus. Dabei wird angenommen, dass Wörter, die zu Suchergebnissen führen, richtig geschrieben sind.
Sollte eine Suche keine Ergebnisse liefern, füllt XSearch das Result-Array mit eventuell gefundenen ähnlichen Wörtern und macht auch einen Vorschlag, wie der neue Suchbegriff aussehen könnte.
Um die Ähnlichkeitssuche effektiv einsetzen zu können, empfiehlt es sich, die Suche selbst mit richtigen Schlagwörtern zu füttern. Dadurch sind erste Suchwörter indexiert und die Ähnlichkeitssuche kann bei einer falschen Schreibweise dieser Wörter diese vorschlagen.
Die Klasse XSearch
Dokumentation der Klasse erstellt mit Doxygen
Tipps, Tricks und FAQ
- Die automatische Indexierung funktioniert nicht für meine ausgewählten Datenbankspalten. Was kann ich tun?
Dieses Problem ist nicht trivial und allumfassend lösbar.
Da das Addon nicht wissen kann, wann eine Datenbankspalte neu indexiert werden muss, kann keine automatische Indexierung erfolgen.
Die Klasse XSearch bietet allerdings die Methode indexColumn an. Über diese Methode können Datenbankspalten neu oder wieder indexiert werden.
Müssen die Datenbankspalten nur zu einem bestimmten Datensatz indexiert werden, kann außerdem die ID dieses Datensatzes angegeben werden.
XSearch wird dann auch nur den betroffenen Datensatz reindexieren.
Beispiel:
Ein Addon arbeitet mit einer eigenen Datenbanktabelle. XSearch soll Inhalte dieses Addons auch automatisch reindexieren.
Da das Addon selbst weiß, wann die Beispieldatenbankspalte "beschreibung" reindexiert werden soll, kann die Methode indexColumn von diesem Addon aufgerufen werden:$xsearch = new XSearch; $xsearch->indexColumn('TABELLE_DES_ADDONS', 'beschreibung', 'id', $datensatz_id);
Die Methode indexColumn benötigt also 4 Parameter:- Die Namen der Datenbanktabelle und
- der Datenbankspalte,
- den Namen der identifizierenden Datenbankspalte und
- die ID des Datensatzes, der aktualisiert wurde.
- Wörter mit Umlauten und Sonderzeichen werden bei der Suche nicht gefunden. Warum ist das so und wie kann ich das beheben?
Es ist sehr wahrscheinlich, dass diese Sonderzeichen als Entitäten kodiert vorliegen (z. B. ü als ü).
Das Problem tritt häufig im Zusammenhang mit TinyMCE auf.
Es gibt zwei Möglichkeiten, um das Problem zu lösen, wobei erstere zu bevorzugen ist:- Die Zeichen müssen "roh" in die Datenbank.
Um das zu erreichen, sollte UTF-8 als Zeichenkodierung genutzt werden.
Außerdem muss der TinyMCE so eingestellt werden, dass er die Zeichen auch roh speichert. Das geht mit der Option entity_encoding : "raw".
Wird der TinyMCE nicht genutzt, dann muss das verwendete Eingabemodul entsprechend konfiguriert oder programmiert werden, dass die Daten roh in die Datenbank kommen. - Nur wenn die erste Lösungsmethode absolut nicht eingesetzt werden kann, kann man die Sucheingabe im Suchmodul mit der PHP-Funktion htmlentities vorbehandeln, bevor sie an die search-Methode weitergereicht wird.
In diesem Zusammenhang sollte auch ein Fehler im Quellcode von Redaxo behoben werden, damit die Daten wirklich UTF-8-kodiert in die Datenbank geschrieben werden: http://forum.redaxo.de/ftopic12127.html
- Die Zeichen müssen "roh" in die Datenbank.
- Ich komme mit der Installation nicht zurecht. Gibt es eine Schritt-für-Schritt-Anleitung?
Ja! ;-)
- XSearch herunterladen: http://www.redaxo.de/180-0-addon-details.html?addon_id=587
- Ordner XSearch in das Addon-Verzeichnis der Redaxo-Installation kopieren/entpacken
- das Addon im Backend installieren und aktivieren
- auf der Seite des Addons gewünschte Einstellungen vornehmen
- auf der Unterseite "Indexierung" die Indexierung starten (ich empfehle die schrittweise Indexierung)
- das Suchformular und eines der Suchmodule einrichten und das Suchmodul in einen Artikel einbinden
Wichtig: Im Suchformular muss die Artikel-ID auf den Artikel mit dem Suchmodul verweisen! - Suche testen
Wenn du die Installation von XSearch genau nachvollziehen möchtest, dann hilft dir das Video von rexvideo.de von Richard Laing weiter.
- Wie kann ich sprachabhängig suchen?
XSearch sucht per Standard in allen Sprachen.
Um sprachabhängige Suchen zu erlauben, muss der Klasse die Sprach-ID der Sprache, in der gesucht werden soll, übergeben werden.
Das geht in einem Suchmodul am einfachsten über die durch Redaxo definierte Konstante REX_CLANG_ID.
Achtung: Die Sprach-ID sollte im Ergebnismodul$xsearch = new XSearch(REX_CLANG_ID);und im Suchformular<input type="hidden" name="clang" value="REX_CLANG_ID" />gesetzt werden.
- Ich habe ein Problem, was hier nicht behandelt wird. Wo kann ich nachfragen?
Im Redaxo-Forum gibt es einen Thread zu diesem Addon: Addon XSearch (Fulltext-Search-Addon)
