Sphinx und SphinxSE ins Zend Framework integrieren
- Sphinx und SphinxSE unter Ubuntu installieren
- Sphinx und SphinxSE ins Zend Framework integrieren
Nachdem Sphinx und SphinxSE installiert ist, geht es diesmal um die Integration in ein Zend Framework-Projekt. Dazu gehört die Erstellung einer Konfigurationsdatei und ein Kommandozeilen-Skript zum Starten und Stoppen des Sphinx-Suchdämons und zum Generieren des Suchindexes.
Den Code zum Artikel gibts auf github.
Das Zend Framework ist nicht enthalten und muss noch nachinstalliert werden. Entweder man lädt sich die aktuelle Version herunter und kopiert oder linkt den Zend-Ordner ins library-Verzeichnis oder man installiert es per PEAR. Den (inoffiziellen) PEAR Channel gibts unter http://pear.zfcampus.org.
Die Konfigurationsdatei
Die Konfigurationsdatei von Sphinx ist die Schaltzentrale und enthält alle Optionen für den Dämon, den Indexer, die Indizes und deren Datenquellen. Für unser Beispielprojekt nutzen wir eine einfache Variante mit Grundeinstellungen. Der Clou ist, dass die Konfigurationsdateien von jeder beliebigen Skriptsprachen verarbeitet werden kann. Einfach am Anfang der Datei den entsprechenden Shebang setzen.
Die Datei liegt in application/configs/sphinx.conf:
#!/usr/bin/env php <?php // Define path to application directory defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/..')); // Define application environment // // Use `export APPLICATION_ENV=development` or edit /etc/environment // to change the application environment defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production')); // Ensure library/ is on include_path set_include_path(implode(PATH_SEPARATOR, array( realpath(APPLICATION_PATH . '/../../library'), get_include_path(), ))); /** Zend_Application */ require_once 'Zend/Application.php'; // Create application, bootstrap, and run $application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini' ); $config = $application->getOptions(); ?> source posts { type = mysql sql_host = <?php echo $config['resources']['db']['params']['host'] . "\n"; ?> sql_user = <?php echo $config['resources']['db']['params']['username'] . "\n"; ?> sql_pass = <?php echo $config['resources']['db']['params']['password'] . "\n"; ?> sql_db = <?php echo $config['resources']['db']['params']['dbname'] . "\n"; ?> # sql_port = 3306 # optional, default is 3306 sql_query_pre = SET NAMES utf8 sql_query = \ SELECT posts.id, posts.category_id, posts.title, posts.content, UNIX_TIMESTAMP(posts.created) AS created, \ categories.name AS category_name, \ GROUP_CONCAT(tags.tag SEPARATOR ', ') AS tags \ FROM posts \ JOIN categories ON (categories.id = posts.category_id) \ LEFT JOIN posts_tags ON (posts_tags.post_id = posts.id) \ LEFT JOIN tags ON (tags.id = posts_tags.tag_id) \ GROUP BY posts.id sql_attr_uint = category_id sql_attr_timestamp = created sql_query_info = \ SELECT posts.id, posts.category_id, posts.title, posts.content, posts.created, \ categories.name AS category_name, \ GROUP_CONCAT(tags.tag SEPARATOR ', ') AS tags \ FROM posts \ JOIN categories ON (categories.id = posts.category_id) \ LEFT JOIN posts_tags ON (posts_tags.post_id = posts.id) \ LEFT JOIN tags ON (tags.id = posts_tags.tag_id) \ WHERE posts.id=$id } index posts { source = posts path = <?php echo $config['sphinx']['index']['path']; ?>/posts docinfo = extern html_strip = 1 charset_type = utf-8 # Character table for german (from http://www.sphinxsearch.com/forum/view.html?id=19) charset_table = 0..9, A..Z->a..z, _, a..z, U+C4->U+E4, U+D6->U+F6, U+DC->U+FC, U+DF, U+E4, U+F6, U+FC } indexer { mem_limit = 32M } searchd { listen = <?php echo $config['sphinx']['searchd']['listen'] . "\n"; ?> log = <?php echo $config['sphinx']['searchd']['log'] . "\n"; ?> query_log = <?php echo $config['sphinx']['searchd']['query_log'] . "\n"; ?> read_timeout = 5 max_children = 30 pid_file = <?php echo $config['sphinx']['searchd']['pid_file'] . "\n"; ?> max_matches = 1000 seamless_rotate = 1 preopen_indexes = 0 unlink_old = 1 }
Was die einzelnen Optionen bedeuten, kann man in der Dokumentation gut nachlesen. Ich will hier nur auf paar Besonderheiten eingehen:
- Der PHP-Abschnitt am Anfang der Datei nutzt
Zend_Applicationum dieapplication.inizu laden. - Im Abschnitt
source postsnutzen wir die ausgelesenen Optionen um die Zugangsdaten für die Datenbank zu setzen. Diese können dann global in derapplication.iniverwaltet werden. - Im Abschnitt
index postsundsearchdverwenden wir ebenfalls Optionen aus derapplication.ini. Das sind vor allem Pfadangaben für den Suchindex und Logdateien und an welcher IP und/oder Port der Suchdämon lauschen soll. Diese Angaben können wir somit proAPPLICATION_ENVanpassen.
Das Kommandozeilen-Skript für Sphinx
Um den Suchindex zu erstellen und den Suchdämon zu starten und zu stoppen, enthält das Projekt das Kommandozeilen-Skript in scripts/sphinx. Der Aufruf erfolgt so:
$ ./scripts/sphinx COMMAND ENVIRONMENT
COMMAND
| start | Startet den Suchdämon. |
|---|---|
| stop | Stoppt den Suchdämon. |
| restart | Startet den Suchdämon neu. |
| index-all | Erstellt alle in application/configs/sphinx.conf definierten Suchindizes. |
ENVIRONMENT
Gibt APPLICATION_ENV an, entspricht also define('APPLICATION_ENV', 'production'); in z. B. der index.php. Somit wird der entsprechende Abschnitt in application/configs/application.ini genutzt. Wenn nicht angegeben, wird standardmäßig production verwendet.
Beispiele
Startet den Suchdämon mit APPLICATION_ENV=production:
$ ./scripts/sphinx start production
Erstellt alle Suchindizes mit APPLICATION_ENV=development:
$ ./scripts/sphinx index-all development
Somit haben wir nun unser Zend Framework-Projekt präpariert um mit Sphinx zu arbeiten. Auf den Suchindex lässt sich nun ganz einfach, z. B. per Zend_Db_Select, zugreifen:
$query = 'Mein Suchbegriff'; $select = $db->select(); $select->from('posts') ->joinInner('sphinx', 'sphinx.id = posts.id') ->where('sphinx.query = ?', $query . ';mode=any;sort=extended:@weight desc, @id asc;limit=10;offset=0;index=posts'); $result = $select->query()->fetchAll();

[...] sorgalla.com wird auch beschrieben, wie SphinxSE mit dem Zend Framework integriert werden kann. Feine Sache! [...]
Sphinx als PHP-Modul einbinden. | SemanticBlog
18 Mrz 10 at 21:35h
Vielen Dank für diesen guten Artikel.
Gibt es noch einen Link zu Benchmarks von MySQL oder o.ä. im Vergleich zu Sphinx(SE)?
David
19 Apr 10 at 18:53h
@David: Einfach mal googeln, da findet sich einiges. Im Sphinx-Blog gab’s vor kurzem Benchmarks von Expressions im Vergleich zu MySQL.
jan
19 Apr 10 at 20:05h