Saludos a todos. Lo primero, comentar que no tengo experiencia con cPanel, pero independientemente de ello, tienes dos formas de utilizar Sphinx dentro de tu sistema, que explico a continuación.
Consideraciones previas
- Sphinx no forma parte de MySQL/Oracle.
- Sphinx es un servidor independiente; una aplicación externa a MySQL, aunque SphinxSE permita cierto grado de integración.
- Sphinx no es solo para MySQL. Se puede integrar también con otras bases de datos relacionales, como PostgreSQL o MS SQL Server.
- Sphinx no es solo para bases de datos, también puede alimentar su índice de ficheros XML o, con una transformación previa, de cualquier otro tipo (txt, pdf, etc...)
Sphinx como motor de almacenamiento de MySQL (SphinxSE)
Esta variedad te permite utilizar Sphinx como motor de almacenamiento en MySQL. En principio para tus necesidades a partir de MySQL 5.1, ya que esta soporta plugins, y te permitirá actualizar MySQL a posteriori sin necesidad de compilar manualmente MySQL cada vez. Otra opción es, por supuesto, compilar MySQL con SPhinx en el binario, pero entiendo que no te interesa.
Si aún asi tienes dudas, siempre puedes instalar un segundo MySQL en otro puerto/carpetas, con otra versión incluso, y utilizar SphinxSE con él, para evitar cualquier intrusión con la estructura de cPanel. O montar tu BD con las tablas sobre las que quieres buscar en PostgreSQL, adjuntarlo a Sphi9nx, e ignorar completamente tu MySQL actual.
Este modelo de instalación te permite realizar consultas a tiempo real (Realtime Indexes), ya que todo lo almacenado se indexa sobre la marcha.
http://sphinxsearch.com/docs/current.html#rt-indexes
Eso si, no soporta cualquier tipo de query MySQL, sino un subset llamado SphinxQL (aunque más que suficiente para el 99% de los casos)
http://sphinxsearch.com/docs/current.html#sphinxql
Consultas típicas con SphinxSE:
Código:
mysql> SELECT * FROM noticias WHERE MATCH('crisis');
mysql> SELECT * FROM noticias WHERE MATCH('@titulo crisis');
Sphinx como demonio independiente
Esta es la opción que siempre he utilizado yo, ignorando toqueteos de MySQL y demás, e instalando Sphinx como demonio independiente (de todas formas, la opción 1 también lo instala tras las bambalinas).
En este modelo, instalas Sphinx y lo configuras diciéndole qué tablas leer para cada índice. Puedes crear un indice de los posts de tu foro y otro diferente de los posts de tu blog, o uno de tus libros con su sinopsis, y otro independiente solo para buscar nombres de autores, etc... y luego dispones de APIs para consultar a este daemon desde PHP, Python, etc... el propio Sphinx ya te trae por ejemplo una librería PHP hecha para conexión y consulta.
En este modelo, obviamente, Sphinx solo sabe qué contenidos hay en MySQL a la hora de lanzar la indexación, no a posteriori, con lo que habría que hacerlo reindexar las tablas cada X tiempo para que vaya "viéndose" el contenido nuevo en el buscador. Sé que a priori puede parecer una mala solución, por aquello de no ser "a tiempo real", pero en el mundo real, pocas ocasiones he visto donde sea totalmente necesario que la búsqueda vaya sincronizada al 100% con el contenido; por lo general, utilizo una configuración main+delta (
http://sphinxsearch.com/docs/2.0.6/delta-updates.html ) donde main reindexa todo el contenido cada hora y delta reindexa lo nuevo cada minuto, de esta forma las reindexaciones de nuevo contenido tardan como mucho 1 minuto en verse, 30 segundos de media. Y esto hablando siempre de grandes índices, si no es el caso, probablemente ni necesites esto, ya que la velocidad de indexación habitual es brutal, un ejemplo real de uno de mis índices en un Kemsirve:
Código:
indexing index 'articulos_index'...
collected 228027 docs, 135.0 MB
sorted 14.8 Mhits, 100.0% done
total 228027 docs, 135037693 bytes
total 9.064 sec, 14896815 bytes/sec, 25155.02 docs/sec
Casi un cuarto de millón de artículos reindexados completamente en 9 segundos, podría perfectamente estar reindexando ese índice cada 5 minutos incluso sin utilizar main+delta. Si hablamos de los posts de un blog o similar, podrías lanzar la reindexación directamente cada vez que publiques/modifiques/elimines un post, y sería realmente a tiempo real, ya que la reindexación llevaría a lo sumo un segundo.
Un ejemplo de consulta desde PHP a un índice sería algo asi:
Código PHP:
require_once "sphinxapi.php";
function MySphinx($Ranker = SPH_RANK_BM25, $MatchMode = SPH_MATCH_FULLSCAN) {
$host = "localhost";
$port = 3312;
$cl = new SphinxClient ();
$cl->SetServer ( $host, $port );
$cl->SetRankingMode ($Ranker);
$cl->SetMatchMode ($MatchMode);
return $cl;
}
$cl = MySphinx();
$cl->SetFilter("provincia", 27); // Un filtro de ejemplo, pueden ser múltiples
$cl->SetFieldWeights ( Array('titulo' => 100, 'anuncio' => 50) ); // Relevancia de donde se encuentre
$cl->SetArrayResult ( true ); // Devolver resultados en formato Array
$cl->SetSortMode ( "fecha" , SPH_SORT_ATTR_DESC ); // Fecha descendente
$res = $cl->Query ("apartamento", "indice_anuncios" ); // Qué buscar y en qué indice
var_dump($res)
Este ejemplo fictíceo nos buscaría en el índice "indice_anuncios" de nuestra web de clasificados, todos los inmuebles que estén en Lugo (provincia 27) y contengan la palabra "apartamento", dando más peso al resultado (100) si el término "apartamento" se encuentra en el título, y menos peso (50) si se encuentra en el cuerpo del anuncio. Finalmente, devolverá primero los que mayor relevancia tengan, y luego, los resultados con relevancia similar nos lo ordenará por nuestro campo fecha de forma descendente. Para acabar la faena, nos lo devolverá en un cómodo formato de Array.
Otras consideraciones
- Necesitarás llamar a un reindexado de vez en cuando para ir agregando los nuevos resultados,
cron sirve perfectamente
- Sphinx no almacena el texto de nuevo, por lo que no puedes decirle "Dame el titulo y el contenido de los posts del blog que contengan 'pepe' ". Por lo general, te devolverá
solo los ids de MySQL (utilizando filtros, se puede traer alguna cosa más), pero es tan trivial como traer los datos con un "SELECT * FROM tabla WHERE id IN (x,y,z)", donde x,y,z son los ids devueltos por Sphinx. Al tratarse de una clave primaria, las búsquedas serán ultrarápidas, del orden de 1 milisegundo.
- Con
SphinxSE esto no es cierto, la query ya puede traerte todos los datos directamente, aunque en mi humilde opinión, con un rendimiento muy inferior.
- Puedes utilizar
múltiples filtros al realizar tu búsqueda, lo que lo convierte en una herramienta muy potente no solo para búsquedas, sino para mostrar resultados categorizados. Utilizas solo el filtro, y una
búsqueda vacía, y te devolverá todos los registros de esa categoría, por lo general, incluso más rápido que el propio MySQL.
- Puedes utilizar
agrupación y ordenar. Esto te permite por ejemplo, realizar un paginado de búsqueda de forma muy sencilla con un
$cl->SetLimits ( $start, $perpage, $maxresults);
- Admite búsqueda aproximada, booleana, exacta... etc.. en la documentación encontrarás de todo
- También puedes buscar en múltiples índices al mismo tiempo, combinando por ejemplo los resultados de dos blogs/foros diferentes, o buscar en noticias y nombres de autores, etc... los índices se pueden combinar.
Script de arranque/parada
SPhinx no incluye un script de arranque/parada, asi que me hice uno propio en su dia, añadiendo funcionalidades además para reindexar. Aqui queda para que lo adapteis a vuestro gusto.
Permite los habituales
Código:
/etc/init.d/sphinx start/stop/restart/status
Así como reindexar un índice concreto, o todos ellos
Código:
/etc/init.d/sphinx reindex mi_indice
Código:
/etc/init.d/sphinx reindex all
Tiene preconfigurado el usuario de Apache porque me gusta poder lanzar, para determinadas partes con muy poco contenido, la reindexación desde PHP, lo que requiere que los ficheros de indice pertenezcan a Apache, y está especificado así también en el script por si se me va la olla y lo corro como root, lo que dejaría los ficheros inaccesibles para la próxima reindexación desde APache.
Sin más, el churro:
Código:
vi /etc/init.d/sphinx
Código:
#!/bin/sh
myuser="www-data"
program="sudo -u $myuser /usr/local/sphinx/bin/searchd"
program_name=Sphinx
program_params="--config /etc/sphinx.conf"
indexer="sudo -u $myuser /usr/local/sphinx/bin/indexer"
indexer_params="--config /etc/sphinx.conf --rotate"
case "$1" in
start)
echo "Starting $program_name"
$program $program_params
echo
;;
stop)
echo "Stopping $program_name"
$program $program_params --stop
echo
;;
status)
estado=$( ps aux | grep $program | grep -v grep | wc -l )
if [ $estado -ne 1 ]
then
echo $program_name esta muerto
else
echo $program_name esta en ejecucion
fi
;;
reindex)
echo "re-Indexing $program_name"
if [ "$2" = "all" ]; then
indexes=" --all"
else
indexes=$2
fi
echo $indexer $indexes $indexer_params
$indexer $indexes $indexer_params
echo
;;
restart)
echo "re-Starting $program_name"
$program $program_params --stop
$program $program_params
echo
;;
*)
echo "Usage: $0 {start|stop|restart|status|reindex one_index or 'all'}"
exit 1
esac
Configuración de un indice
Dejo un ejemplo con dos tablas, con libros en formato epub, y autores, y sus correspondiente indices
epubs_index y epubs_autores_index, de ahí se puede derivar a casi cualquier cosa. Si tenéis alguna duda, comentadme.
Código:
indexer
{
mem_limit = 256M
}
searchd
{
port = 3312
log = /home/sphinx/searchd.log
#query_log = /var/log/query.log
read_timeout = 5
max_children = 30
pid_file = /home/sphinx/searchd.pid
max_matches = 1000
seamless_rotate = 1
preopen_indexes = 0
unlink_old = 1
}
########## LIBRERIA ##############
source epubs
{
type = mysql
sql_host = localhost
sql_user = AQUITUUSERDEMYSQL
sql_pass = AQUITUPASSDEMYSQL
sql_db = AQUITUBD
sql_port = 3306
sql_query_pre = SET NAMES UTF8
sql_query = SELECT libros.id, libros.titulo, libros.id_autor, libros.tematica, autores.autor \
FROM libros \
LEFT JOIN autores ON autores.id = libros.id_autor \
ORDER BY libros.titulo ASC
sql_attr_uint = id_autor
sql_field_string = titulo
sql_ranged_throttle = 0
sql_query_info = SELECT * FROM libros WHERE id=$id
}
source epubs_throttled : epubs
{
sql_ranged_throttle = 1000
}
index epubs_index
{
source = epubs
path = /home/sphinx/epubs_index
docinfo = extern
mlock = 0
morphology = libstemmer_spanish
min_word_len = 3
charset_type = utf-8
html_strip = 1
stopwords =
exceptions =
min_prefix_len = 0
min_infix_len = 0
enable_star = 1
#charset_table = 0..9, A..Z->a..z, a..z, U+C9->U+E9, U+C1->U+E1, \
# U+DA->U+FA, U+D1->U+F1, U+D3->U+F3, U+CD->U+ED, U+E1, \
# U+E9, U+FA, U+F1, U+F3, U+ED
# http://es.wikipedia.org/wiki/ISO_8859-1
charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F,U+C5->U+E5, \
U+E5, U+C4->U+E4, U+E4->a, U+D6->U+F6, U+F6, U+16B, U+0c1->a, U+0c4->a, U+0c9->e, U+0cd->i, \
U+0d3->o, U+0d4->o, U+0da->u, U+0dd->y, U+0e1->a, U+0e4->a, U+0e9->e, U+0ed->i, U+0f3->o, \
U+0f4->o, U+0fa->u, U+0fd->y, U+104->U+105, U+105, U+106->U+107, U+10c->c, U+10d->c, \
U+10e->d, U+10f->d, U+116->U+117, U+117, U+118->U+119, U+11a->e, U+11b->e, U+12E->U+12F, \
U+12F, U+139->l, U+13a->l, U+13d->l, U+13e->l, U+141->U+142, U+142, U+143->U+144, \
U+144,U+147->n, U+148->n, U+154->r, U+155->r, U+158->r, U+159->r, U+15A->U+15B, U+15B, \
U+160->s, U+160->U+161, U+161->s, U+164->t, U+165->t, U+16A->U+16B, U+16B, U+16e->u, \
U+16f->u, U+172->U+173, U+173, U+179->U+17A, U+17A, U+17B->U+17C, U+17C, U+17d->z, \
U+17e->z, U+DC->U+FC, U+DF, U+FC->u, \
U+0D1->U+0F1, U+0F1, \
U+C7->U+E7, U+E7->c, U+C0->a, U+E0->a, U+C8->e, U+E8->e, U+CF->i, U+EF->i, U+D2->o, U+F2->o, \
U+16b->u, U+129->i, \
U+0ED->i, U+0CD->i
}
index epubs_index_stemmed : epubs_index
{
path = /home/sphinx/epubs_index_stemmed
morphology = libstemmer_spanish
}
source epubs_autores : epubs
{
sql_query = SELECT autores.id, autores.id as id_autor, autores.autor FROM autores ORDER BY autores.autor ASC
sql_field_string = autor
sql_query_info = SELECT * FROM autores WHERE id=$id
}
index epubs_autores_index : epubs_index
{
source = epubs_autores
path = /home/sphinx/epubs_autores_index
morphology = libstemmer_spanish
}
Instalación básica del daemon
Código:
cd /tmp
wget http://sphinxsearch.com/files/sphinx-2.0.6-release.tar.gz
tar -xvzf sphinx-2.0.6-release.tar.gz
rm sphinx-2.0.6-release.tar.gz
cd sphinx-2.0.6-release/
wget http://snowball.tartarus.org/dist/libstemmer_c.tgz
tar -xvzf libstemmer_c.tgz
./configure --with-libstemmer --prefix=/usr/local/sphinx
make
make install
mkdir /home/sphinx/
chown www-data.www-data /home/sphinx/
vi /etc/init.d/sphinx
Pegar aquí el script de inicio/parada indicado anteriormente
Código:
chmod +x /etc/init.d/sphinx
vi /etc/sphinx.conf
Realizar aqui la configuración de nuestro primer índice siguiendo el ejemplo de arriba.
Código:
/etc/init.d/sphinx reindex all
Si no hay errores, deben aparecernos ficheros en /home/sphinx , y deberíamos poder realizar nuestra primera consulta utilizando el fichero
sphinxapi.php incluído con la descarga. O si lo preferimos, probar a lanzar una búsqueda desde el cliente de linea de comandos de Sphinx, que también tenemos uno disponible:
Código:
/usr/local/sphinx/bin/search -c /etc/sphinx.conf -i nombre_de_tu_indice palabra a buscar
para buscar en un índice concreto, o
Código:
/usr/local/sphinx/bin/search -c /etc/sphinx.conf palabra a buscar
para buscar en todos.
Una vez comprobado que todo va bien, programaremos en cron un reindexado completo, por ejemplo, cada hora
Código:
# Cada hora, rotación completa del buscador Sphinx
0 * * * * sudo -u www-data /usr/local/sphinx/bin/indexer --config /etc/sphinx.conf --all --rotate > /dev/null
Ejemplos de sitios con búsqueda Sphinx
Portal de cursos, con más de 25000 programas de oferta formativa, tiempo medio de búsqueda,
0.003 segundos:
http://www.portalformativo.com/_incl...&busc_metodo=0
Portal de anuncios clasificados, ejemplo utilizando dos filtros, igualmente rápido, con más de cien mil anuncios clasificados
http://eanuncia.com/busca?q=terrier&a=28&c=4
Sphinx también da soporte a la búsqueda de bitacoras.com, un ingente agregador de blogs español, como podéis ver, de forma muy eficiente, sobre 20.833.417 posts de 576.681 blogs (datos de 2011):
http://bitacoras.com/buscar/ovh
Despedida y cierre
Siento el tocholadrillo, pero era dificil explicar las posibilidades sin entrar en el modo SphinxSE/daemon, y dificil explicar las ventajas de ambos sin extenderse... y una cosa llevó a la otra... y ... lo dicho, que siento el ladrillo.
http://i.imm.io/VuCG.jpeg