Búsquedas «facetadas» en Solr con el soporte de Solrj.

0
12721

Búsquedas «facetadas» en Solr con el soporte de Solrj.

0. Índice de contenidos.


1. Introducción

Después de la introducción a Apache Solr,
y de ver el soporte de solrj
para indexar y recuperar documentos desde java
, en este tutorial vamos a estudiar cómo recuperar metainformación asociada a los resultados de
una consulta.

Las facetas para Solr son subcojuntos de información asociados a los resultados de una consulta que nos permiten agrupar los mismos por distintos
campos de los documentos.

El ejemplo más típico es el de la búsqueda de productos en el que además, recuperamos información sobre cuántos de esos productos pertenecen a cada una
de las categorías de productos existentes. De este modo podremos después afinar la búsqueda de productos, restringiendo los resultados a los productos
asociados a dichas categorías.

Sin el soporte de Solr es lo que, contra una base de datos relacional, tendríamos que hacer con un group by y un count(*).

En Solr, se puede realizar esta operativa en una única consulta, de modo que el resultado de la búsqueda nos devuelva dicha información adicional,
sobre el contenido de la misma.

Además, a partir de la versión 3.1 de Solr, podemos indicar en la consulta que las facetas las cree por rangos, de modo que podríamos recuperar los productos
facetados por rangos de precio.


2. Entorno.

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro 17′ (2.93 GHz Intel Core 2 Duo, 4GB DDR3 SDRAM).
  • Sistema Operativo: Mac OS X Snow Leopard 10.6.7
  • Apache Solr 3.1.
  • Eclipse Helios SR2 con m2eclipse
  • Junit 4.8.2


3. Búsqueda de productos facetados a categorías.

Añadir una faceta a una consulta es tan simple como invocar a los siguientes métodos:

	query.setFacet(true);
	query.addFacetField("cat");

Primero indicamos que queremos hacer uso de facetas y después el o los campos por los que queremos agrupar esa metainformación, en el ejemplo por el campo categoría de producto.

El resultado de una consulta facetada se puede leer de la siguiente forma:

	@Test
	public void retrieveCategoryFacetedResult() throws SolrServerException{
		final SolrQuery query = new SolrQuery(); 
		query.setQuery("name:ipod");
		query.setFacet(true);
		query.addFacetField("cat");

		final QueryResponse response = server.query(query);
		
        final FacetField categoryFacet = response.getFacetField("cat");

        assertFaceted(categoryFacet, "electronics",0,3);
        assertFaceted(categoryFacet, "camera",3,0);
        
	}

	private void assertFaceted(FacetField facet, String name, int categoryPositionInFacet, int productsInCategory) {
        Assert.assertEquals(name,facet.getValues().get(categoryPositionInFacet).getName());
        Assert.assertEquals(productsInCategory,facet.getValues().get(categoryPositionInFacet).getCount());
		
	}

Con ello, lo que conseguimos es poder añadir la siguiente información al resultado de las búsquedas, de modo que el usuario pueda restringir la misma
en función a subconjuntos.



4. Búsqueda de productos facetados por rango de precios.

Si quisieramos añadir rangos a una faceta, por ejemplo para recuperar productos en función a un rango de precios, podríamos hacer algo como lo que sigue:

	@Test
	public void retrievePriceFacetedResult() throws SolrServerException{
		final SolrQuery query = new SolrQuery(); 

		query.setQuery("name:ipod");
		query.setFacet(true);
		
		query.add("facet.range","price");
		query.add("f.price.facet.range.start","0");
		query.add("f.price.facet.range.gap","100");
		query.add("f.price.facet.range.end","1000");
		
		final QueryResponse response = server.query(query);
		// response.getFacetDates() TODO: no existe un getFacetRanges ¿?
        NamedList counts = (NamedList) ((SimpleOrderedMap) 
        					((SimpleOrderedMap) ((SimpleOrderedMap) 
        							response.getResponse().get("facet_counts")).get("facet_ranges")).get("price")).get("counts");
        
        Assert.assertEquals(2, counts.get("0.0"));
        Assert.assertEquals(1, counts.get("300.0"));
	}

A comentar:

  • facet.range: asigna el campo a facetar por rango,
  • f.price.facet.range.start: permite establecer el valor mínimo de precio a facetar,
  • f.price.facet.range.end: permite establecer el precio máximo a facetar,
  • f.price.facet.range.gap: establece el salto entre cada uno de los rangos de la faceta
  • llama la atención que no exista un método directo, o al menos yo no lo he encontrado, para recuperar la faceta por rango.
    Si bien, sí existe para las fechas (getFacetDates()) no existe un método análogo en el api de solrj para recuperar las facetas por rango,
    de ahí la necesidad de recuperarlo manualmente del contenido de la respuesta conociendo las claves de los mapas.


5. Referencias.

  • http://wiki.apache.org/solr/Solrj


6. Conclusiones.

Aunque parece que el api de java aún no está preparado para soportar todo lo que si podemos hacer con xml o json,
seguimos avanzando en el sorprendente mundo de Solr ;).

Un saludo.

Jose

jmsanchez@autentia.com

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad