Apache Solr es una plataforma de búsquedas basada en Apache Lucene, que funciona como un "servidor de búsquedas". Sus principales características incluyen búsquedas de texto completo, resaltado de resultados, clustering dinámico, y manejo de documentos ricos (como Word y PDF). Solr es escalable, permitiendo realizar búsquedas distribuidas y replicación de índices, y actualmente se está usando en muchos de los sitios más grandes de Internet.
La principal característica de Solr (o al menos la más útil) es su API estilo REST, ya que en vez de usar drivers o APIs programáticas para comunicarnos con Solr podemos hacer peticiones HTTP y obtener resultados en XML o JSON. (por cierto, por si tienen curiosidad, se pronuncia "Solar" y no es un acrónimo).
Solr no expone una interfaz REST "perfecta" (que use todos los principios de HTTP 1.1), pero los datos tienen una representación simple que viaja entre el cliente y el servidor, sin ninguna encapsulación rara con SOAP u otras pesadillas. Además, los XML son legibles por personas, y JSON se puede usar para consumir con JavaScript y realizar pruebas.
Las ventajas de usar esta interfaz universal (y no propia de un lenguage) son varias:
- es agnótico del lenguaje porque usa XML y JSON, que hoy en día pueden ser interpretados por casi cualquier cosa. La métrica generalmente es JavaScript: si podemos interpretarlo con JavaScript dentro de todas las limitaciones que impone un navegador, entonces lo podemos interpretar en cualquier otro lugar. Por supuesto, JavaScript tiene soporte nativo para JSON y XML.
- es agnóstico de los tipos de datos, ya que HTTP sólo transmite textos. Los lenguajes dinámicos como PHP tienen éxito porque su protocolo básico no tiene tipos estrictos. Si la presentación lo va a mostrar por pantalla, ¿por qué no debería alcanzar con un string?
- más o menos es un protocolo estándar (aunque la representación de datos no lo sea): si alguien inventa una base de datos y publica sus propio protocolo binario de comunicación, tendríamos muchas más librerías.
Solr está escrito en Java, pero lo podemos usar con nuestro lenguaje preferido, simplemente usando las peticiones GET para realizar búsquedas en el índice, y POST para agregar documentos.
Por supuesto suele haber una librería para cada lenguaje de programación que encapsula la interfaz REST, pero es muy simple construir una librería con, por ejemplo, JavaScript, e igualmente no es obligatorio usarla. Todo esto nos lleva a otro punto: si Solr tuviera una interfaz binaria como MySQL, ¿cómo podríamos invocarla desde JavaScript? HTTP es universal ya que hoy en día hasta casi un secador de pelo puede hacer invocaciones HTTP.
Una pequeña prueba
A diferencia de Lucene, Solr es muy facil de configurar y comenzar a utilizar.
Como la interfaz principal de Solr es web, necesita un contenedor de servlets. Solr tiene varios servlets que exponen distintos servicios, como /update o /select.
Para empezar, lo único que necesitamos es descomprimir la última versión de Solr, ir al directorio example/ y ejecutar el comando:
java -jar start.jar
Esto inicia el servidor de Solr con un esquema de documentos de ejemplo. Ya estamos listos para agregar documentos y ejecutar consultas!
Creando una prueba JUnit
Vamos a usar la librería Java para insertar un documento y realizar una búsqueda. Este API en realidad es un wrapper de la interfaz HTTP, y nos permite acceder a Solr muy facilmente desde Java. Hay que recordar que esta misma funcionalidad la podríamos realizar con peticiones HTTP directas al servidor.
import java.io.IOException; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collection; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; import org.apache.solr.client.solrj.impl.XMLResponseParser; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrInputDocument; import org.junit.After; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; public class SolrTest { /* Esta es la URL donde se encuentra levantado el servidor de Solr. */ private static final String URL = "http://localhost:8983/solr"; private CommonsHttpSolrServer server; /** Lo primero es establecer la conexión al servidor, representada por el objeto CommonsHttpSolrServer. */ @Before public void before() throws MalformedURLException { server = new CommonsHttpSolrServer(URL); server.setParser(new XMLResponseParser()); } /** Al terminar la prueba vamos a borrar todos los registos, para tener un * índice limpio la próxima vez que corramos la prueba. */ @After public void after() throws SolrServerException, IOException { server.deleteByQuery("*:*"); } /** Esta prueba ingresa un documento, lo busca, y por último borra todo el contenido del índice para dejar todo limpio para la próxima vez. */ @Test public void buscar() throws MalformedURLException, SolrServerException, IOException { //creamos un documento de Solr para insertar. //los campos están definidos en Solr, y no podemos usar campos no definidos. SolrInputDocument doc1 = new SolrInputDocument(); doc1.addField("id", "123", 1.0f); doc1.addField("name", "un documento de prueba", 1.0f); Collection<SolrInputDocument> docs = new ArrayList<SolrInputDocument>(); docs.add(doc1); server.add(docs); server.commit(); //buscamos el documento. //la sintaxis básica de búsqueda es "campo:texto". En este caso, estamos //buscando la palabra "prueba" en el campo "name". //Si quisieramos buscar todos los documentos, pondriamos "*:*" SolrQuery query = new SolrQuery(); query.setQuery("name:prueba"); QueryResponse rsp = server.query(query); SolrDocumentList docList = rsp.getResults(); assertTrue(docList.size() == 1); assertEquals("123", docList.get(0).get("id")); } }
Con qué seguir
Esta fue sólo una muy pequeña introducción al uso de Solr. En la documentación de Solr pueden empezar a darse cuenta de las capacidades de este motor de búsquedas, como la replicación de índices (para lograr alta disponibilidad y escalar facilmente) o el sharding de contenido (un índice distribuido, con partes viviendo en distintos servidores pero accedidos como si fueran una única instancia).
Otra cosa para probar es AJAX Solr, una librería JavaScript que accede directamente a Solr para realizar consultas y poder crear interfaces ricas de forma muy rápida.