Я разработал, как рассчитать разумные динамические грани для диапазонов цен на товары. Решение предполагает некоторую предварительную обработку документов и некоторую пост-обработку результатов запроса, но для 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]
Может быть, на шесть лет поздно на вечеринку, но ссылки больше не работают. – Bucket
@DesertIvy Обязательно посмотрите их на archive.org или в другом месте и отредактируйте ответ. –
Ничего себе, даже не знал, что существует. Отличный инструмент! – Bucket