Resultados de SOLR en formato Opensearch

OpenSearch  es una colección de tecnologías que permiten publicar resultados de búsqueda en un formato estándar que es adecuado para sindicación y agregación.

Es posible configurar Solr para que devuelva resultados en formato OpenSearch. Para ello solo hay que (1) configurar una hoja de transformación XSL que transforme nuestros documentos y (2) publicar un fichero de descripción.

1) Configurar XSL

Es el propio SOLR el que hace la transformación si así se indica con los parámetros : wt y tr.

El parámetro wt selecciona el response writer que Solr usará para formatear la respuesta. En nuestro caso: wt=xslt.

El response writer XSLT admite un parámetro (tr) que identifica la transformación del XML que se va a usar. Esta transformación debe encontrarse en el directorio conf/xslt de solr. En nuestro caso: tr=opensearch.xsl

Por ejemplo:

http://azeotropes-solr:8983/solr/COLLECTION_shard1_replica1/select?q=azeotropes&wt=xslt&indent=true&tr=opensearch.xsl

 

El siguiente código muestra el fichero xslt/opensearch.xsl, que es el que utilizaremos para la transformación del xml.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" encoding="utf-8" indent="yes" media-type="application/atom+xml;charset=UTF-8" />
 <xsl:template match="/">
 <xsl:variable name="searchTerms" select="response/lst[@name='responseHeader']/lst[@name='params']/str[@name='q']" />
 <xsl:variable name="totalHits" select="response/result/@numFound" />
 <xsl:variable name="searchTimeSecs" select="number(response/lst[@name='responseHeader']/int[@name='QTime']) div 1000.0" />
 <xsl:variable name="start">
 <xsl:choose>
 <xsl:when test="response/lst[@name='responseHeader']/lst[@name='params']/str[@name='start'] != ''">
 <xsl:value-of select="response/lst[@name='responseHeader']/lst[@name='params']/str[@name='start']" />
 </xsl:when>
 <xsl:otherwise>
 <xsl:value-of select="0" />
 </xsl:otherwise>
 </xsl:choose>
 </xsl:variable>
 <xsl:variable name="rows">
 <xsl:choose>
 <xsl:when test="response/lst[@name='responseHeader']/lst[@name='params']/str[@name='rows'] != ''">
 <xsl:value-of select="response/lst[@name='responseHeader']/lst[@name='params']/str[@name='rows']" />
 </xsl:when>
 <xsl:otherwise>
 <xsl:value-of select="20" />
 </xsl:otherwise>
 </xsl:choose>
 </xsl:variable>
 <xsl:variable name="totalPages" select="ceiling(number($totalHits) div number($rows))" />
 <xsl:variable name="currentPage" select="ceiling(number($start) div number($rows))" />
 <feed xmlns="http://www.w3.org/2005/Atom" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"> <title>MBArtists search results for: <xsl:value-of select="$searchTerms" /></title>
 <subtitle><xsl:value-of select="$totalHits" /> results found in <xsl:value-of select="$searchTimeSecs" /> seconds.</subtitle>
 <logo>http://azeotropes-solr:8983/web/logo.png</logo>
<updated><xsl:value-of select="response/result/doc[position()=1]/date[@name='timestamp']" /></updated>
 <author><name>Azeotropes::Solr/Lucene</name></author>
 <id>tag:localhost:<xsl:value-of select="$searchTerms" /></id>
 <opensearch:totalResults><xsl:value-of select="$totalHits" /></opensearch:totalResults>
 <opensearch:startIndex><xsl:value-of select="$start" /></opensearch:startIndex>
 <opensearch:itemsPerPage><xsl:value-of select="$rows" /></opensearch:itemsPerPage>
 <opensearch:Query role="request" searchTerms="{$searchTerms}" startPage="1" />
 <!-- You might want to add another stylesheet to emit HTML... 
 <link rel="alternate" type="text/html" 
 href="select?q={$searchTerms}&amp;wt=xslt&amp;tr=as_html.xsl&amp;start=TODO&amp;rows=TODO" />
 -->
 <!-- 
 You should use XPath 2.0 functions to "escape-uri" these link href state transitions.
 See http://wiki.apache.org/solr/XsltResponseWriter for help on switching to XPath 2.0 
 -->
 <link rel="self" type="application/atom+xml" 
 href="select?q={$searchTerms}&amp;wt=xslt&amp;tr=opensearch_atom.xsl&amp;start={$start}&amp;rows={$rows}" />
 <link rel="first" type="application/atom+xml"
 href="select?q={$searchTerms}&amp;wt=xslt&amp;tr=opensearch_atom.xsl&amp;start=0&amp;rows={$rows}" />
 <xsl:choose>
 <xsl:when test="number($start) &gt; number($rows)">
 <xsl:variable name="previous" select="(number($currentPage) - 1) * number($rows)" />
 <link rel="previous" type="application/atom+xml"
 href="select?q={$searchTerms}&amp;wt=xslt&amp;tr=opensearch_atom.xsl&amp;start={$previous}&amp;rows={$rows}" />
 </xsl:when>
 </xsl:choose>
<xsl:choose>
 <xsl:when test="number($totalHits) &gt; number($rows) and (number($totalHits) - number($start)) &gt; number($rows)">
 <xsl:variable name="next" select="(number($currentPage) + 1) * number($rows)" />
 <link rel="next" type="application/atom+xml"
 href="select?q={$searchTerms}&amp;wt=xslt&amp;tr=opensearch_atom.xsl&amp;start={$next}&amp;rows={$rows}" /> 
 </xsl:when>
 </xsl:choose>
 <link rel="last" type="application/atom+xml"
 href="select?q={$searchTerms}&amp;wt=xslt&amp;tr=opensearch_atom.xsl&amp;start={number($totalHits) - 1}&amp;rows={$rows}" />
 <!-- autodiscovery tag -->
 <link rel="search" type="application/opensearchdescription+xml"
 href="opensearch_description.xml" />
 <xsl:for-each select="response/result/doc">
 <xsl:variable name="id" select="str[@name='id']" />
 <entry>
 <title>
 <xsl:value-of select="str[@name='a_name']" />
 </title>
 <link href='select?q=id:"{$id}"' />
 <id>tag:localhost:<xsl:value-of select="$id" /></id>
 <summary>
 <xsl:value-of select="arr[@name='a_name']" />
 </summary>
 <updated>
 <xsl:value-of select="date[@name='indexedAt']" />
 </updated>
 </entry>
 </xsl:for-each> 
 </feed>
 </xsl:template>
</xsl:stylesheet>

Los resultados tienen el formato de feeds Atom.

2) Publicar un fichero de descripción OpenSearch

Además es necesario publicar un fichero de descripción en un servidor http del mismo dominio. Este fichero XML define la consulta y los parámetros de búsqueda permitidos:

<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
 <ShortName>Azeotropes - Solr Example Search with Opensearch</ShortName>
 <Url type="application/atom+xml" template="http://azeotropes-solr:8983/solr/COLLECTION_shard1_replica1/select?q={searchTerms}&wt=xslt&tr=opensearch.xsl"/>
</OpenSearchDescription>

 

Este es un fichero mínimo, pero se puede completar con más información si fuese necesario, tal y como indica la especificación de OpenSearch.

 

Anuncios

PLN en Apache Spark

logo

Se ha liberado bajo licencia Apache 2.0 una librería de Procesamiento de Lenguaje Natural (en inglés NLP). Está escrita en Scala y no tiene dependencias con otras librerías de PLN. Está construido sobre Apache Spark y Spark ML y ofrece una solución escalable  dentro de contextos Bigdata.

La librería en cuestión es “John Snow Labs NLP Library” que extiende los Pipelines de Spark ML  para ofrecer las siguientes funcionalidades:

  • Tokenizer
  • Normalizador
  • Stemmer y Lematizador
  • Extractor de entidades y fechas
  • POS Tagger
  • Reconocimiento de Entidades Nombradas (Named Entities)
  • Detección de límites de oraciones
  • Análisis de sentimiento
  • Spell checker

 

Enlaces:

 

Arquitectura lambda aplicada a clustering de documentos en contextos Big Data

La aplicación de técnicas de minería de datos, concretamente de clustering, sobre grandes volúmenes de datos (Big Data) supone un desafío en cuanto a la escalabilidad y al tiempo de respuesta, ya que cantidades crecientes de datos implican tiempos mayores de computación. La arquitectura lambda es un conjunto de recomendaciones de propósito general para diseñar una arquitectura en escenarios Big Data de forma que se resuelva el problema de la latencia y se puedan obtener resultados en tiempo real. En este trabajo se presenta un estudio aplicando la arquitectura lambda sobre el clustering de documentos en contextos Big Data. La problemática que se desea resolver es la elevada latencia que tiene lugar cuando se introducen nuevos documentos en el sistema que realiza clustering. Uno de los puntos clave sugeridos por esta arquitectura es la separación del procesamiento en tres capas: batch layer, speed layer y serving layer. Una problemática adicional al tratar documentos es su elevada dimensionalidad y este problema se soslaya mediante reducción de dimensionalidad con Latent Dirichlet Allocation. Los experimentos se han llevado a cabo utilizando el framework Apache Spark y demuestran que esta combinación de capas permite realizar clustering sobre grandes volúmenes de datos y disponer de resultados actualizados en tiempo real, con calidad del clustering comparable a trabajos similares sobre contextos no Big Data.

Arquitectura lambda aplicada a clustering de documentos en contextos Big Data

VALLEJO MARTÍNEZ, Alberto; MARTÍNEZ UNANUE, Raquel; RODRIGO YUSTE, Álvaro. Arquitectura lambda aplicada a clustering de documentos en contextos bigdata. 2015.