2008-08-29 10 views
15

Załóżmy, że mam pole o nazwie cena dla dokumentów w Solr i mam to pole fasetowane. Chcę uzyskać fasety jako zakresy wartości (np .: 0-100, 100-500, 500-1000, itp.). Jak to zrobić?Jak uzyskać zakresy facetów w wynikach solr?

Mogę określić zakresy wcześniej, ale chcę również wiedzieć, czy możliwe jest automatyczne obliczenie zakresów (np. Dla 5 wartości) w oparciu o wartości w dokumentach?

Odpowiedz

4

Może być lepsza odpowiedź na Solr, ale pracuję z prostą Lucene, a ponieważ nie robisz zbyt dużej trakcji, zrobię ukłucie. Tam utworzyłem opcję Filter z opakowaniem FilteredQuery oryginalnego Query. Wtedy otrzymam FieldCache dla pola zainteresowania. Wylicz hity w zestawie bitowym filtru, a dla każdego trafienia otrzymasz wartość pola z pamięci podręcznej pól i dodaje ją do zestawu SortedSet. Po uzyskaniu wszystkich trafień podziel rozmiar zestawu na liczbę żądanych zakresów (od pięciu do siedmiu jest liczbą odpowiednią dla użytkowników interfejsu), a zamiast pojedynczej wartości ograniczenia, być zapytaniem o zakres z dolnym i górnym limitem każdego z tych podzbiorów.

Polecam użycie specjalnej logiki dla niewielkiej liczby wartości; oczywiście, jeśli masz tylko cztery różne wartości, nie ma sensu próbować z nich 5 zawężeń zakresu. Poniżej pewnego progu (powiedzmy 3 * Twojej idealnej liczby zakresów), pokazujesz tylko aspekty, a nie zakresy.

14

Aby odpowiedzieć na pierwsze pytanie, można uzyskać zakresy aspektów za pomocą ogólnej obsługi zapytań do aspektów. Here „s przykład:

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

Co do drugiego pytania (automatycznie sugeruje fazowane zakresy), który nie jest jeszcze zaimplementowana. Niektórzy twierdzą, że tego typu zapytania najlepiej byłoby zastosować w twojej aplikacji, niż pozwolić Solrowi na "odgadywanie" najlepszych zakresów aspektów.

Oto niektóre dyskusje na ten temat:

+1

Może być sześć lat spóźniony na imprezę, ale linki już nie działają. – Bucket

+1

@DesertIvy Na wszelki wypadek spójrz na archiwa.org lub gdzieś indziej i edytuj odpowiedź. –

+0

Wow, nawet nie wiedziałem, że istnieje. Świetne narzędzie! – Bucket

6

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]