Aplikacja „sprzedaż samochodów” – Unicode Collation, czyli sortowanie wyników wyszukiwania uwzględniając język danych (cz. 4)

W trzeciej części cyklu dodaliśmy dane lokalizacyjne oraz informacje o miejscowości, z którego pochodzi auto. Wkrótce potem dodaliśmy również możliwość sortowania po miejscowości, w prosty sposób modyfikując schemę:

<field name="city_sort" type="lowercase" indexed="true" stored="false" />
...
<copyField source="city" dest="city_sort"/>

Okazało się jednak, że sortowanie po miejscowości (pole city_sort) nie funkcjonuje tak jak powinno, a wszystko ze względu na występowanie w nazwach miast polskich znaków. Co z tym zrobić ?

Analiza wymagań

Sprawdźmy, czy faktycznie sortowanie po polu „city_sort” nie uwzględnia polskich znaków. Zadajmy zapytanie:

q=*:*&fl=city&sort=city_sort+asc

Otrzymujemy rezultat:

<result name="response" numFound="6" start="0">
   <doc>
      <str name="city">Białystok</str>
   </doc>
   <doc>
      <str name="city">Koszalin</str>
   </doc>
   <doc>
      <str name="city">Szczecin</str>
   </doc>
   <doc>
      <str name="city">Warszawa</str>
   </doc>
   <doc>
      <str name="city">Świdnik</str>
   </doc>
   <doc>
      <str name="city">Łowicz</str>
   </doc>
</result>

Rzeczywiście, wyniki nie są posortowane poprawnie. Oczekiwaliśmy takiego rezultatu:

<result name="response" numFound="6" start="0">
   <doc>
      <str name="city">Białystok</str>
   </doc>
   <doc>
      <str name="city">Koszalin</str>
   </doc>
   <doc>
      <str name="city">Łowicz</str>
   </doc>
   <doc>
      <str name="city">Szczecin</str>
   </doc>
   <doc>
      <str name="city">Świdnik</str>
   </doc>
   <doc>
      <str name="city">Warszawa</str>
   </doc>
</result>

W celu usprawnienia sortowania danych zawierających polskie znaki wykorzystamy filtr „solr.CollationKeyFilter”.

solr.CollationKeyFilter

Filtr solr.CollationKeyFilter jest wykorzystywany podczas indeksowania, dodając do indeksu specjalne „klucze sortujące”. Pozwala nam na wskazanie kolatora powiązanego z konkretnym krajem i językiem. Możemy również określić „siłę” kolatora, która definiuje pewien minimalny poziom różnic jaki jest brany pod uwagę przy porównywaniu. Przykład:

<filter class="solr.CollationKeyFilterFactory" language="es" country=”ES” strength="primary" />

Powyższy przykład jest definicją fabryki dla filtra solr.CollationKeyFilter, określającego kolator dla języka hiszpańskiego z siłą primary.

Zmiany w schema.xml

  1. Definicja nowych typów pól:
      <fieldType name="polishLowercase" positionIncrementGap="100">
        <analyzer>
          <tokenizer class="solr.KeywordTokenizerFactory"/>
          <filter class="solr.LowerCaseFilterFactory" />
          <filter class="solr.TrimFilterFactory" />
          <filter class="solr.CollationKeyFilterFactory"  language="pl" country=”PL” strength="primary" />
        </analyzer>
      </fieldType>

      Jak widać jest to tak naprawdę definicja już istniejącego typu „lowercase” uzupełnionego o filtr solr.CollationKeyFilter, określającego kolator dla języka polskiego. Będziemy używać tego typu pola do definiowania pól, które zawierają dane z polskimi znakami.

  2. Zmiana definicji pola „city_sort”:
    • zmieniamy typ dla pola „city_sort” na nowo zdefiniowany typ „polishLowercase”:
    • <field name="city_sort" type="polishLowercase" indexed="true" stored="false" />

Testy funkcjonalności

Zanim przetestujemy, czy zmiana typu pola przyniosła oczekiwany rezultat, pamiętajmy, że filtr solr.CollationKeyFilter wykorzystywany w tym typie działa na etapie indeksacji. Należy zatem wykonać pełną reindeksację danych.

Sprawdźmy teraz wynik zapytania, które wykorzystaliśmy wcześniej do przetestowania jakości sortowania:

q=*:*&fl=city&sort=city_sort+asc

Jak się okazuje, otrzymujemy oczekiwany wcześniej, poprawny rezultat:

<result name="response" numFound="6" start="0">
   <doc>
      <str name="city">Białystok</str>
   </doc>
   <doc>
      <str name="city">Koszalin</str>
   </doc>
   <doc>
      <str name="city">Łowicz</str>
   </doc>
   <doc>
      <str name="city">Szczecin</str>
   </doc>
   <doc>
      <str name="city">Świdnik</str>
   </doc>
   <doc>
      <str name="city">Warszawa</str>
   </doc>
</result>

Podsumowanie

Kolejny zgłoszony problem został pomyślnie rozwiązany. Usprawniliśmy jakość wyników sortowania po polskich znakach, wykorzystując nieskomplikowany, ale jakże pomocny filtr solr.CollationKeyFilter. Czekamy na dalsze zgłoszenia 🙂

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *