RankField i Rank Query Parser

Jedną z funkcjonalności o których nie mieliśmy jeszcze okazji pisać, jest nowy typ pól nazwany RankField oraz o nowym parserze – Rank Query Parser. Korzystając z obu wspomnianych nowości mamy możliwość wpływania na score dokumentów za pomocą funkcji operujących na wartościach pól. Spójrzmy zatem co wspomniana para ma do zaoferowania.

Funkcjonalność Rank Query Parser

Funkcjonalność Rank Query Parser jest dość prosta. Pozwala on na modyfikowanie score dokumentu na podstawie jednej z dostępnych funkcji operującej na wartości zawartej w polu tego dokumentu. Można zatem powiedzieć, iż dostarcza wycinka funkcjonalności dostępnej za pomocą Function Query Parser. Nowością jest jednak możliwość wykorzystania algorytmu BlockMax-WAND, aby zwiększyć wydajność naszego zapytania.

Pola typu RankField

Korzystanie z nowego typu pół, czyli z RankField jest bardzo proste. Wszystko co potrzebujemy zrobić do zdefiniowanie odpowiedniego typu pola, pola i rozpoczęcie indeksowania danych. Załóżmy, iż nasze dokumentu posiadają następującą strukturę:

{
  "id" : 1,
  "name": "RankField and RankQueryParser",
  "type": "post",
  "views": 1000 
}

Mamy zatem identyfikator dokumentu, nazwę dokumentu, jego typ oraz liczbę wyświetleń. Interesują nas wartości z tego ostatniego. Załóżmy, iż chcielibyśmy, aby wartości z tego pola były brane pod uwagę podczas obliczania score dokumentu – im więcej wyświetleń, tym wyżej dokument powinien być w wynikach wyszukiwania. W przypadku naszych dokumentów struktura danych opisana w pliku schema.xml wygląda następująco:

<field name="id" type="string" />
<field name="name" type="text_ws" />
<field name="type" type="string" />
<field name="views" type="rank" />

Oczywiście, musimy także zdefiniować nasz nowy typ rank, którego definicja mogłaby wyglądać następująco:

<fieldType name="rank" class="solr.RankField" />

I to jest wszystko czego potrzebujemy, czas na zapytania.

Korzystanie z Rank Query Parser

Aby skorzystać z Rank Query Parser i wykorzystać informacje z pola views w celu wpływania na score możemy wykorzystać zapytanie podobne do następującego:

q=_query_:{!rank f='views' function='log'}

Przed zadaniem zapytania zaindeksowaliśmy następujące dokumenty:

[
  {
    "id" : 1,
    "name": "RankField and RankQueryParser",
    "type": "post",
    "views": 1000 
  },
  {
    "id" : 2,
    "name": "Lucene and Solr 8.6.1 were released",
    "type": "announcement",
    "views": 10
  }
]

A wyniki zapytania wygląda następująco:

{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":3,
    "params":{
      "q":"_query_:{!rank f='views' function='log'}",
      "fl":"score,*"}},
  "response":{"numFound":2,"start":0,"maxScore":6.908755,"numFoundExact":true,"docs":[
      {
        "id":"1",
        "name":"RankField and RankQueryParser",
        "type":"post",
        "_version_":1678886835690930176,
        "score":6.908755},
      {
        "id":"2",
        "name": "Lucene and Solr 8.6.1 were released",
        "type":"announcement",
        "_version_":1678886835758039040,
        "score":2.3978953}]
  }}

Można zauważyć, iż pomimo tego, że zadaliśmy zapytanie match all, które nadaje każdemu z dokumentów score o wartości 1.0 wszystkim pasującym dokumentom nasz score jest inny. Solr wziął pod uwagę wartość zwróconą przez funkcję log dla każdego z dokumentów.

Wydajność

Oczywiście, to samo co powyżej moglibyśmy osiągnąć stosując Function Query Parser. Kluczem jest natomiast to, iż Rank Query Parser wspiera algorytm BlockMax-WAND. W przypadku kiedy do naszego zapytania dodamy parametr minExactCount ustawiony na liczbę dokumentów, które muszą pasować do zapytania Solr jest w stanie pominąć te dokumenty, które nie trafią do top N. Oczywiście zrobi to tylko wtedy, kiedy warunek określony przez minExactCount zostanie osiągnięty.

Wynik zapytania z parametrem minExactCount wygląda następująco:

{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":1,
    "params":{
      "q":"_query_:{!rank f='views' function='log'}",
      "fl":"score,*",
      "minExactCount":"1"}},
  "response":{"numFound":2,"start":0,"maxScore":6.908755,"numFoundExact":true,"docs":[
      {
        "id":"1",
        "name":"RankField and RankQueryParser",
        "type":"post",
        "_version_":1678886835690930176,
        "score":6.908755},
      {
        "id":"2",
        "name":"Lucene and Solr 8.6.1 were released",
        "type":"announcement",
        "_version_":1678886835758039040,
        "score":2.3978953}]
  }}

O samym algorytmie BlockMax-WAND i jego wykorzystaniu w Solr porozmawiamy sobie w następnych wpisach. Jest trochę plusów i minusów o których fajnie porozmawiać.

Dostępne funkcje

W momencie powstawania tego wpisu dostępne były następujące funkcje, z których mogliśmy skorzystać wykorzystując Rank Query Parser:

  • log – funkcja logarytmiczna, wykorzystuje atrybuty  weight oraz scalingFactor
  • satu – funkcja akceptujące atrybuty pivot oraz weight
  • sigm – funkcja akceptująca atrybuty pivotweight, oraz exponent 

W ramach naszego zapytania możemy skorzystać z jednej z wyżej wymienionych funkcji i wykorzystać ją do modyfikacji score naszych dokumentów.

Podsumowanie

Pomimo tego, iż wcześniej podobną funkcjonalność mogliśmy już w Solr uzyskać, to jednak wsparcie dla algorytmu BlockMax-WAND jest dosyć dużym plusem. W sytuacjach kiedy mamy możliwość zadawania zapytań i nie potrzebujemy dokładnej informacji na temat liczby zwróconych wyników wyszukiwania to Rank Query Parser wydaje się być funkcjonalnością, na którą warto spojrzeć.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.