2008-08-29 6 views
15

Предположим, что у меня есть поле под названием цена для документов в Solr, и у меня есть это поле ограненное. Я хочу получить грани в виде диапазонов значений (например: 0-100, 100-500, 500-1000 и т. Д.). Как это сделать?Как получить диапазоны грани в результатах solr?

Я могу заранее задать диапазоны, но также хочу знать, можно ли автоматически рассчитывать диапазоны (например, для 5 значений) на основе значений в документах?

ответ

4

Может быть, лучше, чем Solr-специфический ответ, но я работаю с прямой Lucene, а так как вы не получаете большой тяги, я возьму удар. Там, я бы создал населенность Filter с FilteredQuery обертывая оригинал Query. Тогда я получу FieldCache для интересующей области. Перечислите хиты в битрейтете фильтра, и для каждого удара вы получите значение поля из кеша поля и добавьте его в SortedSet. Когда у вас есть все хиты, разделите размер набора на количество диапазонов, которые вы хотите (пять-семь - это хорошее число в соответствии с парнями пользовательского интерфейса), а не однозначное ограничение, ваши грани будут быть запросом диапазона с нижней и верхней границами каждого из этих подмножеств.

Я бы рекомендовал использовать некоторую специальную логику для небольшого числа значений; очевидно, если у вас есть только четыре разных значения, нет смысла пытаться сделать из него 5 уточнений диапазона. Ниже определенного порога (скажем, 3 * ваше идеальное количество диапазонов) вы просто показываете грани, а не диапазоны.

14

Чтобы ответить на ваш первый вопрос, вы можете получить диапазоны фасет, используя поддержку общего запроса фасетов. Here «пример:

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

Что касается Вашего второго вопроса (автоматически предполагая фасеты диапазонов), который еще не реализован. Некоторые утверждают, что такой запрос будет лучше всего реализован в вашем приложении, а это позволит Solr «угадать» лучшие диапазоны фасет.

Вот некоторые дискуссии по теме:

+1

Может быть, на шесть лет поздно на вечеринку, но ссылки больше не работают. – Bucket

+1

@DesertIvy Обязательно посмотрите их на archive.org или в другом месте и отредактируйте ответ. –

+0

Ничего себе, даже не знал, что существует. Отличный инструмент! – Bucket

6

Я разработал, как рассчитать разумные динамические грани для диапазонов цен на товары. Решение предполагает некоторую предварительную обработку документов и некоторую пост-обработку результатов запроса, но для Solr требуется только один запрос, и он должен работать даже с старой версией Solr, как 1.4.

Круглый вверх цены до подачи

Во-первых, перед отправкой документа облавы от цены до ближайшей «хорошей границей круглый фасет» и сохранить его в поле «rounded_price». Такие пользователи, как их грани, выглядят как «250-500», а не «247-483», а округление также означает, что вы получаете сотни ценовых граней, а не миллионы.С некоторым усилием следующий код может быть обобщена округлить красиво в любой ценовой шкале:

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; 
    } 

Допустимые цены взлетают 1,2,3, ..., 24,25,30,35, ..., 95100110 , ..., 240 250 275 300 325, ..., 975,1000 и т. Д.

Получить все грани на округлых цены

Во-вторых, при подаче запроса, запрос все аспекты по закругленными цен, отсортированный по цене: facet.field=rounded_price. Благодаря округлению вы получите не более нескольких сотен граней назад.

Объединить смежные грани в больших граней

В-третьих, после того, как у вас есть результаты, пользователь хочет видеть только 3 до 7 граней, а не сотни граней. Итак, объедините смежные грани в несколько больших граней (называемых «сегментами»), пытаясь получить примерно одинаковое количество документов в каждом сегменте. Следующий более сложный код делает это, возвращая кортежи (start, end, count), подходящие для выполнения запросов диапазона. Подсчеты возвращаемые будет правильно предоставленные цены были округлены до до ближайшей границы:

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; 
    } 

Фильтр по выбранным фаской

В-четвертых, предположим, что («250», «500», 38) было один из полученных сегментов. Если пользователь выбирает «от $ 250 до $ 500» в качестве фильтра, просто сделайте запрос на фильтрацию fq=price:[250 TO 500]

Смежные вопросы