Index für Volltextsuche

Trick zur Beschleunigung der Suche

Da eine Volltextsuche mit Related Tables zu absurd hohen Zeiten beim Ausführen der Queries führt (mit vielen Joins) habe ich hier einen Ausweg gefunden, der funktioniert solange

  • die Daten nur im Backend editiert werden
  • die Tabellen über mm Relation verbunden sind

Beim Speichern im Backend wird in ein eigenes Feld namens "full_text" eine kommaseparierte Liste der Einträge in Related Tables geschrieben.

Hook für Speichern im Backend

ext_localconf.php

include "class.tx_rsyssocialprojects_compat.php";
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = 'tx_rsyssocialprojects_compat';

Klasse

class.tx_rsyssocialprojects_compat.php:


<?php

class tx_rsyssocialprojects_compat {

    /**
     * executed on save in backend
     *
     * @param    string        status: new/update is relevant for us
     * @param    string        db table
     * @param    integer        record uid
     * @param    array        record
     * @param    object        parent object
     * @return    void
     */
    function processDatamap_postProcessFieldArray($status, $table, $id, &$fieldArray, $pObj) {

        if($table == 'tx_rsyssocialprojects_domain_model_project' && ($status == 'new' || $status == 'update')) {
            if($status == 'update') {
                $data = $this->getFullRecord($id);
            } else {
                $data = $fieldArray;
            }
       
            $newRecord = array_merge($data, $fieldArray);
           
            $combinedName = '';
            $combinedName .= $this->getRelated('admission', $id);
            $combinedName .= $this->getRelated('goal', $id);
            $combinedName .= $this->getRelated('place', $id);
            $combinedName .= $this->getRelated('projecttype', $id);
            $combinedName .= $this->getRelated('schooltype', $id);
            $combinedName .= $this->getRelated('targetgroup', $id);
           
            # write to fulltext field
            $fieldArray['full_text'] = $combinedName;
        }
    }

    /**
     * gets a full tx_rsyssocialprojects_domain_model_project record
     *
     * @param    integer    $uid: lookup uid
     * @return    array    data record with associative keys
     */
    function getFullRecord($uid) {
        $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
                '*',
                'tx_rsyssocialprojects_domain_model_project',
                'uid = '.$uid
        );

        return $row[0];
    }
   
    /**
     * gets a record from a related table
     *
     * @param    string    $name: table name
     * @param    string    $uid: lookup uid
     * @return    array    data record with associative keys
     */
    function getRelated($name, $uid) {
        $ret = '';
        $res = $GLOBALS['TYPO3_DB']->sql_query(
                'SELECT a.title FROM tx_rsyssocialprojects_domain_model_project p
                LEFT JOIN  tx_rsyssocialprojects_project_'.$name.'_mm mm ON mm.uid_local = p.uid
                LEFT JOIN  tx_rsyssocialprojects_domain_model_'.$name.' a ON mm.uid_foreign = a.uid
                WHERE p.uid='.$uid
        );
        while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
            $ret .=  ','.$row['title'];
        }
        return $ret;
    }

}

if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/tt_data/class.tx_ttdata_compat.php'])    {
    include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/tt_data/class.tx_ttdata_compat.php']);
}

?>

Nun kann man bei der Volltextsuche ganz entspannt in dem Feld full_text suchen bei optimaler Performance. Vielen Dank an Sigi für die Idee hierzu :-)

So sieht das dann aus:

// related tables are stored in full text on save in backend
$query->like('fullText', "%".$searchText."%"),

   
// related tables - way too slow                   
//$query->like('projectTypes.title', "%".$searchText."%"),
//$query->like('targetGroups.title', "%".$searchText."%"),
//$query->like('goals.title', "%".$searchText."%"),
//$query->like('places.title', "%".$searchText."%"),
//$query->like('admissions.title', "%".$searchText."%"),
//$query->like('schoolTypes.title', "%".$searchText."%"),

Erstellt: 09/2012| Geändert: 10/2015