Dowiedziałem się, jak obliczyć rozsądne dynamiczne aspekty dla przedziałów cenowych produktów. Rozwiązanie obejmuje wstępne przetwarzanie dokumentów i pewne przetwarzanie wyników zapytań, ale wymaga tylko jednego zapytania do Solr, a nawet powinno działać w starej wersji Solr, takiej jak 1.4.
zaokrąglić w górę ceny przed złożeniem
pierwsze, przed złożeniem dokumentu runda się w cena do najbliższego „ładny okrągły facet granicy” i przechowywać go w „rounded_price” pola. Użytkownicy lubią swoje aspekty, aby wyglądać jak "250-500", a nie "247-483", a zaokrąglanie oznacza również, że otrzymujesz setki aspektów cenowych, a nie miliony.Z pewnym wysiłkiem następujący kod można uogólnić ładnie zaokrąglić w dowolnej skali cena:
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;
}
Dopuszczalne ceny idą 1,2,3, ..., 24,25,30,35, ..., 95100110 , ..., 240,250,27, 300,325, ..., 975 000 i tak dalej.
Uzyskaj wszystkie aspekty na zaokrąglonych cenach
drugie, przy składaniu zapytania zwrócić wszystkie aspekty dotyczące zaokrąglonych cenach posortowane według ceny: facet.field=rounded_price
. Dzięki zaokrągleniu otrzymasz co najwyżej kilkaset aspektów.
łączyć sąsiadujące aspekty do większych aspektach
trzecie, po masz wyniki, gdy użytkownik chce zobaczyć tylko 3 do 7 aspektów, nie setki aspektach. Tak więc połącz sąsiednie aspekty z kilkoma dużymi aspektami (zwanymi "segmentami"), starając się uzyskać w przybliżeniu taką samą liczbę dokumentów w każdym segmencie. Powoduje to następujący bardziej skomplikowany kod, zwracając krotki (start, end, count) odpowiednie do wykonywania zapytań dotyczących zasięgu. Liczy zwracane będą poprawne przewidzianych ceny były zaokrąglono się do najbliższej granicy:
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;
}
Wyszukane przez wybranego aspektu
czwarte, załóżmy („250”, „500”, 38) był jeden z powstałych segmentów. Jeśli użytkownik wybierze "250 $ do 500 $" jako filtr, po prostu zrób zapytanie filtrujące: fq=price:[250 TO 500]
Może być sześć lat spóźniony na imprezę, ale linki już nie działają. – Bucket
@DesertIvy Na wszelki wypadek spójrz na archiwa.org lub gdzieś indziej i edytuj odpowiedź. –
Wow, nawet nie wiedziałem, że istnieje. Świetne narzędzie! – Bucket