Data Import Handler – import danych z plików Solr XML

Do tej pory, w poprzednich artykułach, przyglądaliśmy się importowi danych z baz SQL. Dziś przyszedł czas na import z plików XML.

Przykład

Popatrzmy na następujący przykład:

<dataConfig>
  <dataSource type="FileDataSource" />
  <document>
    <entity
      name="document"
      processor="FileListEntityProcessor"
      baseDir="/home/import/data/2011-06-27"
      fileName=".*\.xml$"
      recursive="false"
      rootEntity="false"
      dataSource="null">
      <entity
        processor="XPathEntityProcessor"
        url="${document.fileAbsolutePath}"
        useSolrAddSchema="true"
        stream="true">
      </entity>
    </entity>
  </document>
</dataConfig>

Objaśnienie przykładu

W porównaniu z przykładami z wcześniejszych części pojawiło się wykorzystanie źródła danych typu FileDataSource. Przykład pełnego wywołania:

<dataSource
  type="FileDataSource"
  basePath="/home/import/input"
  encoding="utf-8"/>

dodatkowe, nieobowiązkowe atrybuty są w zasadzie oczywiste:

  • basePath – podaje katalog względem którego będzie określane położenie plików podane w tagu „entity”
  • encoding – określa kodowanie plików (domyślnie: kodowanie domyślne systemu)

Po definicji źródła następuje definicja dokumentu z dwoma, zagnieżdżonymi opisami encji.

Zadaniem głównej encji jest wygenerowanie listy plików. Do tego celu wykorzystywany jest FileListEntityProcessor. Encja jest w zasadzie samowystarczalna i do jej działania nie jest potrzebne żadne źródło danych (dlatego: dataSource=”null”). Atrybuty wykorzystywane to:

  • fileName (wymagane) – wyrażenie regularne, określające które pliki należy pobrać
  • recursive – czy pliki szukane będą również w podkatalogach (domyślnie: nie)
  • rootEntity – określa czy dane z encji są traktowane jako źródło dokumentów. Ponieważ nie chcemy indeksować listy plików, które dostarcza encja, tylko zawartość dokumentów, to pole musi być ustawione na wartość „false”. Dzięki temu następna zdefiniowana encja automatycznie zostanie potraktowana jako główna i jej dane (dokumenty) zostaną zindeksowane.
  • baseDir (wymagane) katalog, w którym poszukiwane będą pliki
  • dataSource – w tym wypadku „null”, gdyż encja nie korzysta z żadnego źródła. (W zasadzie w solr > 1.3 parametr ten można po prostu pominąć)
  • excludes – wyrażenie regularne określające, które pliki pominąć przy wyszukiwaniu
  • newerThan – określa datę w formacie: YYYY-MM-dd HH:mm:ss Może to być również napis w pojedynczych cudzysłowach np. ‚NOW – 7DAYS’ lub dostępna zmienna zawierająca datę: ${nazwa}. Określa, że tylko nowsze pliki od tej daty będą brane po uwagę
  • olderThan – jw. tylko dla starszych plików
  • biggerThan – określa rozmiar pliku – tylko większe pliki będą brane pod uwagę
  • smallerThan – jw. dla mniejszych plików

Mając już listę plików, do akcji wchodzi kolejna, wewnętrzna encja – jej zadaniem jest już pobranie konkretnych danych, zawartych w plikach. Dane pobierane są z pliku podanego przez zewnętrzną encję za pomocą źródła danych. Typ procesora: XpathEntityProcessor używany do plików XML rozpoznaje następujące atrybuty:

  • url – namiary na dane wejściowe
  • useSolrAddSchema – informacja, że dane wejściowe są w postaci Solr XML.
  • stream – czy zastosować przetwarzanie strumieniowe. W przypadku dużych XML warto użyć stream=”true” co zmniejszy zapotrzebowanie na pamięć a czasem wręcz umożliwi import ;))

Dodatkowe parametry nie są przydatne w naszym przykładzie i opiszemy je przy innej okazji 🙂

Ale po co to wszystko?

Przykład umożliwia on odczytanie wszystkich plików XML z wybranego katalogu. Jako format pliku używany tu jest dokładnie ten sam format jak przy „klasycznej” metodzie wysyłania dokumentów do SOLR przy pomocy HTTP POST. Dlaczego więc korzystać z tej metody?

Push i Pull

Pierwszym argumentem może być kontrola nad połączeniami między sewerem SOLR a systemem serwującym dane do importu. Gdy nie mamy pełnej kontroli nad źródłem danych, lepiej pobierać dane ze źródła, niż udostępniać dodatkowy serwis, który potencjalnie może stać się celem ataku.

Prototypowanie i testowanie zmian

Drugi argument, ważniejszy dla programisty: DIH umożliwia w prosty sposób manipulowanie treścią pobieranego dokumentu. Jest to bardzo sympatyczna cecha pozwalająca na np. dodania do dokumentu paru pól, bez konieczności przerabiania całego mechanizmu generującego pliki XML.

Jak to działa w praktyce? W moim wypadku postanowiono dodać możliwość bardziej zaawansowanego wyszukiwania i facetingu po drzewie kategorii. W dokumencie było już dostępne pole „category” przechowujące ścieżkę typu: „Samochody / Osobowe / Audi”. By umożliwić stworzenie nowych zapytań w indeksie powinny pojawić się dodatkowe pola mówiące o tym, jaka jest kategoria, na którym jest poziomie oraz ile jest wszystkich poziomów.

By dodać wymagane pola wykorzystaliśmy możliwość definiowania skryptów. Wcześniej zacytowany plik importu teraz wygląda tak:

<dataConfig>
  <script><![CDATA[
    function CategoryPieces(row) {
      var pieces = row.get('category').split('/');
      var arr = new Array();
      for (var i=0; i < pieces.length; i++) {
        row.put('category_level_' + i, pieces[i].trim());
        arr[i] = pieces[i].trim();
      }
      row.put('category_level_max', (pieces.length - 1).toFixed());
      row.put('category', arr.join('/'));
      return row;
  }
  ]]></script>
  <dataSource type="FileDataSource" />
  <document>
    <entity
      name="document"
      processor="FileListEntityProcessor"
      baseDir="/home/import/data/2011-06-27"
      fileName=".*\.xml$"
      recursive="false"
      rootEntity="false"
      dataSource="null">
      <entity
        processor="XPathEntityProcessor"
        transformer=”script:CategoryPieces”
        url="${document.fileAbsolutePath}"
        useSolrAddSchema="true"
        stream="true">
      </entity>
    </entity>
  </document>
</dataConfig>

Uwaga na zakończenie

Stosując DIH trzeba mieć świadomość, że działa on trochę inaczej. W szczególności próba wczytania wielu wartości do pola nie zaznaczonego w schema.xml jako „multiValued” w DIH zakończy się sukcesem – nadmiarowe wartości zostaną zignorowane. W przypadku „klasycznego” sposobu będzie zwrócony błąd.

This post is also available in: angielski

This entry was posted on wtorek, Sierpień 16th, 2011 at 08:19 and is filed under Solr, Tutorial. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.