Как получить диапазоны фасетов в результатах Solr? - PullRequest
15 голосов
/ 29 августа 2008

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

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

Ответы [ 4 ]

14 голосов
/ 04 октября 2008

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

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

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

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

7 голосов
/ 04 июля 2012

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

Округлить цены перед отправкой

Сначала, перед отправкой документа, округлите округление цены до ближайшей «границы хорошего круглого фасета» и сохраните ее в поле «округленный_ценой». Пользователям нравится, что их грани выглядят как «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 аспектов, а не сотни аспектов. Итак, объедините смежные грани в несколько больших граней (называемых «сегментами»), пытаясь получить примерно равное количество документов в каждом сегменте. Следующий довольно сложный код делает это, возвращая кортежи (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]

4 голосов
/ 15 мая 2012

Вы можете использовать диапазон фасов solr

http://wiki.apache.org/solr/SimpleFacetParameters#Facet_by_Range

4 голосов
/ 29 августа 2008

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...