2008-08-29 17 views
15

Supongamos que tengo un campo llamado precio para los documentos en Solr y tengo ese campo facetado. Quiero obtener las facetas como rangos de valores (por ejemplo: 0-100, 100-500, 500-1000, etc.). ¿Cómo hacerlo?¿Cómo obtener rangos de facetas en los resultados de solr?

Puedo especificar los rangos de antemano, pero también quiero saber si es posible calcular los rangos (por ejemplo, para 5 valores) automáticamente en función de los valores en los documentos?

Respuesta

4

Es posible que haya una mejor respuesta específica para Solr, pero trabajo con Lucene directo, y como no estás obteniendo mucha tracción, daré una puñalada. Allí, crearía un populate a Filter con un FilteredQuery envolviendo el Query original. Entonces obtendría un FieldCache para el campo de interés. Enumere los aciertos en el conjunto de bits del filtro, y para cada acierto, obtiene el valor del campo de la memoria caché de campo y lo agrega a SortedSet. Cuando tenga todos los hits, divida el tamaño del conjunto en el número de rangos que desee (de cinco a siete es un buen número de acuerdo con la interfaz de usuario chicos), y en lugar de una restricción de un solo valor, sus facetas ser una consulta de rango con los límites inferior y superior de cada uno de esos subconjuntos.

Recomendaría utilizar alguna lógica de caso especial para una pequeña cantidad de valores; obviamente, si solo tiene cuatro valores distintos, no tiene sentido tratar de hacer 5 refinamientos de rango de ellos. Por debajo de un cierto umbral (digamos 3 * su número ideal de rangos), simplemente muestra las facetas normalmente en lugar de rangos.

14

Para responder a su primera pregunta, puede obtener rangos de facetas mediante el uso del soporte de consulta de facetas genérico. Here 's un ejemplo:

http://localhost:8983/solr/select?q=video&rows=0&facet=true&facet.query=price:[*+TO+500]&facet.query=price:[500+TO+*] 

En cuanto a su segunda pregunta (lo que sugiere automáticamente los rangos de faceta), que aún no está implementado. Algunos argumentan que este tipo de consultas se implementaría mejor en su aplicación en lugar de dejar que Solr "adivine" los mejores rangos de facetas.

Estas son algunas discusiones sobre el tema:

+1

podría ser de seis años tarde a la fiesta, pero los enlaces no funcionan. – Bucket

+1

@DesertIvy Por supuesto, búsquelos en archive.org o en otro lugar y edite la respuesta. –

+0

Wow, ni siquiera sabía que existía. ¡Gran herramienta! – Bucket

6

He calculado cómo calcular las facetas dinámicas sensibles para los rangos de precios de los productos. La solución implica un preprocesamiento de documentos y un procesamiento posterior de los resultados de la consulta, pero solo requiere una consulta a Solr, e incluso debería funcionar en la versión anterior de Solr como 1.4.

Round Up precios antes de su presentación

En primer lugar, antes de presentar el documento, ronda hasta el el precio más cercana a la "buena faceta límite redonda" y almacenarlo en un campo "rounded_price". A los usuarios les gustan sus facetas para que parezcan "250-500", no "247-483", y el redondeo también significa que recuperas cientos de facetas de precio, no millones de ellas.Con un poco de esfuerzo el siguiente código se puede generalizar para redondear muy bien en cualquier escala de precios:

public static decimal RoundPrice(decimal price) 
    { 
     if (price < 25) 
      return Math.Ceiling(price); 
     else if (price < 100) 
      return Math.Ceiling(price/5) * 5; 
     else if (price < 250) 
      return Math.Ceiling(price/10) * 10; 
     else if (price < 1000) 
      return Math.Ceiling(price/25) * 25; 
     else if (price < 2500) 
      return Math.Ceiling(price/100) * 100; 
     else if (price < 10000) 
      return Math.Ceiling(price/250) * 250; 
     else if (price < 25000) 
      return Math.Ceiling(price/1000) * 1000; 
     else if (price < 100000) 
      return Math.Ceiling(price/2500) * 2500; 
     else 
      return Math.Ceiling(price/5000) * 5000; 
    } 

precios permisibles van 1,2,3, ..., 24,25,30,35, ..., 95100110 , ..., 240,250,275,300,325, ..., 975,1000 y así sucesivamente.

conseguir todas las facetas de los precios redondeados

En segundo lugar, el momento de presentar la consulta, solicitar todas las facetas sobre los precios redondeados ordenados por precio: facet.field=rounded_price. Gracias al redondeo, obtendrás como máximo unos cientos de facetas.

Combinar facetas adyacentes en las facetas más grandes

En tercer lugar, después de tener los resultados, el usuario quiere ver sólo de 3 a 7 facetas, no cientos de facetas. Por lo tanto, combine las facetas adyacentes en algunas facetas grandes (llamadas "segmentos") tratando de obtener una cantidad aproximadamente igual de documentos en cada segmento. El siguiente código bastante más complicado hace esto, devolviendo tuplas de (inicio, fin, recuento) adecuadas para realizar consultas de rango. Los recuentos devueltos serán precios proporcionados correctas se han redondeado hasta al límite más cercano:

public static List<Tuple<string, string, int>> CombinePriceFacets(int nSegments, ICollection<KeyValuePair<string, int>> prices) 
    { 
     var ranges = new List<Tuple<string, string, int>>(); 
     int productCount = prices.Sum(p => p.Value); 
     int productsRemaining = productCount; 
     if (nSegments < 2) 
      return ranges; 
     int segmentSize = productCount/nSegments; 
     string start = "*"; 
     string end = "0"; 
     int count = 0; 
     int totalCount = 0; 
     int segmentIdx = 1; 
     foreach (KeyValuePair<string, int> price in prices) 
     { 
      end = price.Key; 
      count += price.Value; 
      totalCount += price.Value; 
      productsRemaining -= price.Value; 
      if (totalCount >= segmentSize * segmentIdx) 
      { 
       ranges.Add(new Tuple<string, string, int>(start, end, count)); 
       start = end; 
       count = 0; 
       segmentIdx += 1; 
      } 
      if (segmentIdx == nSegments) 
      { 
       ranges.Add(new Tuple<string, string, int>(start, "*", count + productsRemaining)); 
       break; 
      } 
     } 
     return ranges; 
    } 

Filtrar los resultados por faceta

En cuarto lugar, supongamos seleccionado ("250", "500", 38) era uno de los segmentos resultantes. Si el usuario selecciona "$ 250 a $ 500" como un filtro, simplemente hacer una consulta de filtro fq=price:[250 TO 500]

Cuestiones relacionadas