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




Вполне может быть лучший ответ для Solr, но я работаю с прямым Lucene, и, поскольку вы не получаете особой тяги, я возьму удар. Там я бы создал заполненный Filter с FilteredQuery, обернув исходный Query. Тогда я бы купил FieldCache для интересующей области. Перечислите попадания в битовом наборе фильтра, и для каждого попадания вы получите значение поля из кеша полей и добавите его в SortedSet. Когда у вас есть все совпадения, разделите размер набора на количество диапазонов, которое вы хотите (от пяти до семи - хорошее число в соответствии с пользовательским интерфейсом, ребята), и вместо однозначного ограничения ваши фасеты будут быть запросом диапазона с нижней и верхней границами каждого из этих подмножеств.
Я бы рекомендовал использовать логику особых случаев для небольшого числа значений; очевидно, что если у вас есть только четыре различных значения, нет смысла пытаться сделать из них 5 уточнений диапазона. Ниже определенного порога (скажем, 3 * ваше идеальное количество диапазонов) вы просто обычно показываете фасеты, а не диапазоны.
Чтобы ответить на ваш первый вопрос, вы можете получить диапазоны фасетов, используя общую поддержку фасетных запросов. Пример Здесь:
http://localhost:8983/solr/select?q=video&rows=0&facet=true&facet.query=price:[*+TO+500]&facet.query=price:[500+TO+*]
Что касается вашего второго вопроса (автоматически предлагающего диапазоны фасетов), он еще не реализован. Некоторые утверждают, что этот вид запросов лучше всего реализовать в вашем приложении, а не позволять Solr «угадывать» наилучшие диапазоны фасетов.
Вот несколько дискуссий по теме:
@DesertIvy Обязательно найдите их на archive.org или где-нибудь еще и отредактируйте ответ.
Вау, даже не знал, что это существует. Отличный инструмент!
Вы можете использовать диапазоны фасетов solr
http://wiki.apache.org/solr/SimpleFacetParameters#Facet_by_Range
Я разработал, как рассчитать разумные динамические аспекты для диапазонов цен на продукты. Решение включает в себя некоторую предварительную обработку документов и некоторую пост-обработку результатов запроса, но для этого требуется только один запрос к 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, ..., 95,100,110, ..., 240,250,275,300,325, ..., 975,1000 и так далее.
Во-вторых, при отправке запроса запросите все аспекты округленных цен, отсортированных по цене: facet.field=rounded_price. Благодаря округлению вы получите не более нескольких сотен граней.
В-третьих, после того, как у вас есть результаты, пользователь хочет видеть только от 3 до 7 аспектов, а не сотни аспектов. Итак, объедините смежные фасеты в несколько больших фасетов (называемых «сегментами»), пытаясь получить примерно равное количество документов в каждом сегменте. Следующий, более сложный код делает это, возвращая кортежи (начало, конец, счет), подходящие для выполнения запросов диапазона. Возвращенные значения будут правильными при условии, что цены были округлены вверх до ближайшей границы:
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].
Может быть, на вечеринку опоздаешь на шесть лет, но ссылки больше не работают.