Como implementar Sphinx con symfony

Como primera aproximación a un buscador simple en la primera versión de Voota, se nos ocurrió utilizar “Google custom search“. Mala idea. Hoy, 5 días después de la puesta online, Google solo ha indexado 267 páginas y teniendo en cuenta que empezábamos con 1.549 políticos con sus 1.549 correspondientes fichas, los resultados no eran muy apropiados. Por ejemplo, buscando “Zapatero” aparecían varios resultados del blog, alguna ficha de otros políticos y varios enlaces al ranking, pero no la ficha del sr. presidente.

Necesitábamos un buscador, sencillo, potente y que escalase bien con los futuros desarrollos que vienen. La solución fue mucho más fácil de lo esperado. Decidimos implementar nuestro propio motor de búsqueda con Sphinx. Así es como lo hicimos:

  1. Lo primero es instalar el motor de búsqueda, que básicamente consta de dos partes: El indexador, que obtiene las palabras clave de la base de datos (Postgresql o mysql) y el demonio o servicio de búsqueda que atiende a las peticiones del servidor web.
    La instalación no tiene más misterio que seguir los pasos que explican en su web: Manual de referencia de Sphinx.
  2. Después viene la fase de configuración. Aquí es donde se le dice a Sphinx que datos tiene que indexar para que puedan ser encontrados en el buscador del sitio web. En nuestro caso, de momento, sólo queríamos indexar los políticos:
    source src1
    {
    type                                    = mysql
    sql_host                                = localhost
    sql_user                                = usuario
    sql_pass                                =
    sql_db                                  = voota
    sql_port                                = 3306  # optional, default is 3306
    sql_query_pre   = SET NAMES utf8
    sql_query                               = \
    SELECT id, vanity, alias, nombre, apellidos, bio, presentacion, residencia, formacion \
    FROM politico
    sql_ranged_throttle     = 0
    sql_query_info          = SELECT * FROM politico WHERE id=$id
    }
    source src1throttled : src1
    {
    sql_ranged_throttle                     = 100
    }
    index politico
    {
    source                  = src1
    path                    = /var/data/voota
    docinfo                 = extern
    mlock                   = 0
    morphology              = none
    min_word_len            = 1
    charset_type            = utf-8
    charset_table   = 0..9, A..Z->a..z, a..z, \
    U+C0->a, U+C1->a, U+C2->a, U+C3->a, \
    U+C4->a, U+C5->a, U+C6->a, \
    U+C7->c,U+E7->c, U+C8->e, U+C9->e, \
    U+CA->e, U+CB->e, U+CC->i, \
    U+CD->i, U+CE->i, U+CF->i, U+D0->d, \
    U+D1->n, U+D2->o, U+D3->o, \
    U+D4->o, U+D5->o, U+D6->o, U+D8->o, \
    U+D9->u, U+DA->u, U+DB->u, \
    U+DC->u, U+DD->y, U+DE->t, U+DF->s, \
    U+E0->a, U+E1->a, U+E2->a, U+E3->a, \
    U+E4->a, U+E5->a, U+E6->a, \
    U+E7->c,U+E7->c, U+E8->e, \
    U+E9->e, U+EA->e, U+EB->e, U+EC->i, \
    U+ED->i, U+EE->i, U+EF->i, \
    U+F0->d, U+F1->n, U+F2->o, U+F3->o, \
    U+F4->o, U+F5->o, U+F6->o, \
    U+F8->o, U+F9->u, U+FA->u, U+FB->u, \
    U+FC->u, U+FD->y, U+FE->t, U+FF->s,
    html_strip                              = 0
    }

    Extracto del fichero de configuración de Sphinx

  3. A continuación se arranca el servicio de búsqueda:
    sudo searchd –config /usr/local/etc/sphinx.conf
    y se da la orden para que Sphinx realice la indexación (Esto será necesario hacerlo periódicamente):
    sudo /usr/local/bin/indexer politico –rotate
    Muy bien, Sphinx configurado y escuchando.
  4. Sólo falta escribir el código Symfony para interrogar al motor de búsqueda:
    $this->q = $request->getParameter(“q”);$cl = new SphinxClient ();
    $cl->SetServer ( ‘localhost’, 3312 );
    $this->limit = 1000;
    $cl->SetLimits ( 0, $this->limit, $this->limit );
    $cl->SetArrayResult ( true );
    $this->res = $cl->Query ( SfVoUtil::stripAccents( $this->q ), ‘politico’ );
    if ( $this->res!==false ) {
    if ( isset($this->res[“matches”]) && is_array($this->res[“matches”]) ) {
    $c = new Criteria();
    $list = array();
    foreach ($this->res[“matches”] as $idx => $match) {
    $list[] = $match[‘id’];
    }
    $c->add(PoliticoPeer::ID, $list, Criteria::IN);
    $c->addDescendingOrderByColumn(PoliticoPeer::SUMU);
    $this->politicosPager = new sfPropelPager(‘Politico’, 10);
    $this->politicosPager->setCriteria($c);
    $this->politicosPager->setPage($this->getRequestParameter(‘page’, 1));
    $this->politicosPager->init();if ($this->politicosPager->getNbResults() == 1){
    $res = $this->politicosPager->getResults();
    $this->redirect( “@politico_”.$this->getUser()->getCulture( ‘es’ ).”?id=”.$res[0]->getVanity() );
    }
    }
    }

    Código Symfony que realiza la búsqueda

Listo, hoy puedes buscar Zapatero, José Luis Rodriguez o ZP en Voota, que seguro que encuentras lo que buscas, a no ser que quieras comprarte unos zapatos nuevos, claro 😉

Anuncios

Etiquetas: , ,

10 comentarios to “Como implementar Sphinx con symfony”

  1. Carlos Says:

    Oooooohhhh!!!! genial.
    Gracias Sergio.
    Creo que vamos a copiartelo. 😉

  2. Sergio Viteri Says:

    ¡Genial! Si quieres comentar algo, ya sabes donde estamos 😀

  3. David Says:

    Hola Sergio. Y por qué implementar Lucene mediante este plugin?
    http://www.symfony-project.org/plugins/sfLucenePlugin

    Un saludo y sigue así, acabo de descubrirte desde symfony.es y la verdad es que el blog y el proyecto de Voota lo encuentro muy interesante.

  4. Sergio Viteri Says:

    Hola David, gracias por el comentario.

    Lucene es una buena alternativa sin duda. El problema que tiene es que es Java y orientado a Java, mientras que Sphinx se utiliza mucho más con proyectos php (aunque es independiente del lenguaje). Nos gusta estar siempre alineados con el mercado. Siempre es bueno a la hora de buscar ayuda o preguntar a la comunidad 😉

    Saludos!

  5. David Says:

    Gracias Sergio. Lo tendré en cuenta cuando lo implemente en mi proyecto. Yo la verdad es que tenía pensado basarme en Zend Lucene para crear un buscador, siguiendo el tutorial oficial:
    http://www.symfony-project.org/jobeet/1_4/Doctrine/es/17

    Sin embargo, a la vista de tu experiencia (gracias de nuevo por compartirla) consideraré Sphinx (que, la verdad sea dicha, no conocía).

    Gracias!

  6. Sergio Viteri Says:

    Seguro que ambas opciones son buenas 🙂

    Ya nos contarás cual implementas al final y cómo te va. Suerte.

  7. Sergio Lepore Says:

    Señor! LLego a su web casi por casualidad debido a que estoy en pleno desarrollo de un proyecto en el cual necesitaba hacer uso de un motor de busquedas eficiente..me encuentro con Sphinx pero no tenia idea de quien pudo implementarlo ni como! pero justo encuentro su web!

    muchas gracias por compartir esta informacion! no sabe cuan util me ha sido! gracias! exitos!

  8. Fernando Says:

    Hola sergio, tu clase SphinxClient de donde sale de un plugin?

  9. Sergio Viteri Says:

    Hola Fernando,

    No es un plugin, es una de las clases que provee el cliente de Sphinx para php. Puede echar un ojo en el sitio de Sphinx ( http://sphinxsearch.com/wiki/doku.php?id=php_api_docs ) o bajarte directamente la versión que utilizamos en Voota: https://github.com/voota/voota/blob/master/www/lib/sphinxapi.php (que es básicamente lo mismo).

  10. Alex Castillo Says:

    Saludos, desde mexico, muy buena explicacion, una duda fuera del tema, la integracion con facebook la hicieron con el Plugin Facebook connect, tengo tiempo liado con el y no he podido echarlo andar, espero me puediras ayudar con el tema

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s


A %d blogueros les gusta esto: