[Java] Как получить диапазоны фасет в результатах solr?


Answers

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

Question

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

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