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 *

We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners. View more
Cookies settings
Accept
Privacy & Cookie policy
Privacy & Cookies policy
Cookie name Active
Save settings
Cookies settings