<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>data import handler &#8211; Solr.pl</title>
	<atom:link href="https://solr.pl/tag/data-import-handler/feed/" rel="self" type="application/rss+xml" />
	<link>https://solr.pl</link>
	<description>All things to be found - Blog related to Apache Solr &#38; Lucene projects - https://solr.apache.org</description>
	<lastBuildDate>Wed, 11 Nov 2020 20:22:03 +0000</lastBuildDate>
	<language>pl-PL</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>
	<item>
		<title>Data Import Handler – import danych z plików Solr XML</title>
		<link>https://solr.pl/2011/08/16/automatycznie-zapisany-szkic/</link>
					<comments>https://solr.pl/2011/08/16/automatycznie-zapisany-szkic/#respond</comments>
		
		<dc:creator><![CDATA[Rafał Kuć]]></dc:creator>
		<pubDate>Tue, 16 Aug 2011 19:20:08 +0000</pubDate>
				<category><![CDATA[Ogólna]]></category>
		<category><![CDATA[data import handler]]></category>
		<category><![CDATA[dih]]></category>
		<category><![CDATA[solr]]></category>
		<guid isPermaLink="false">http://sematext.solr.pl/?p=313</guid>

					<description><![CDATA[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: &#60;dataConfig&#62; &#60;dataSource type="FileDataSource" /&#62; &#60;document&#62; &#60;entity name="document" processor="FileListEntityProcessor" baseDir="/home/import/data/2011-06-27" fileName=".*\.xml Objaśnienie przykładu W porównaniu]]></description>
										<content:encoded><![CDATA[<p>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.</p>
<p><span id="more-313"></span></p>
<h2>Przykład</h2>
<p>Popatrzmy na następujący przykład:
</p>
<pre class="brush:xml">&lt;dataConfig&gt;
  &lt;dataSource type="FileDataSource" /&gt;
  &lt;document&gt;
    &lt;entity
      name="document"
      processor="FileListEntityProcessor"
      baseDir="/home/import/data/2011-06-27"
      fileName=".*\.xml
<h2>Objaśnienie przykładu</h2>
<p>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:
</p>
<pre class="brush:xml">&lt;dataSource
  type="FileDataSource"
  basePath="/home/import/input"
  encoding="utf-8"/&gt;</pre>
<p>dodatkowe, nieobowiązkowe atrybuty są w zasadzie oczywiste:</p>
<ul>
<li><strong>basePath</strong> – podaje katalog względem którego będzie określane położenie plików podane w tagu „entity”</li>
<li><strong>encoding</strong> – określa kodowanie plików (domyślnie: kodowanie domyślne systemu)</li>
</ul>
<p>Po definicji źródła następuje definicja dokumentu z dwoma, zagnieżdżonymi opisami encji.</p>
<p>Zadaniem głównej encji jest wygenerowanie listy plików. Do tego celu wykorzystywany jest <strong>FileListEntityProcessor</strong>. Encja jest w zasadzie samowystarczalna i do jej działania nie jest potrzebne żadne źródło danych (dlatego: dataSource=”null”). Atrybuty wykorzystywane to:</p>
<ul>
<li><strong>fileName</strong> (wymagane) – wyrażenie regularne, określające które pliki należy pobrać</li>
<li><strong>recursive</strong> – czy pliki szukane będą również w podkatalogach (domyślnie: nie)</li>
<li><strong>rootEntity</strong> – 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.</li>
<li><strong>baseDir</strong> (wymagane) katalog, w którym poszukiwane będą pliki</li>
<li><strong>dataSource</strong> – w tym wypadku „null”, gdyż encja nie korzysta z żadnego źródła. (W zasadzie w solr &gt; 1.3 parametr ten można po prostu pominąć)</li>
<li><strong>excludes</strong> – wyrażenie regularne określające, które pliki pominąć przy wyszukiwaniu</li>
<li><strong>newerThan</strong> – 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ę</li>
<li><strong>olderThan</strong> – jw. tylko dla starszych plików</li>
<li><strong>biggerThan</strong> – określa rozmiar pliku – tylko większe pliki będą brane pod uwagę</li>
<li><strong>smallerThan</strong> – jw. dla mniejszych plików</li>
</ul>
<p>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: <strong>XpathEntityProcessor</strong> używany do plików XML rozpoznaje następujące atrybuty:</p>
<ul>
<li><strong>url</strong> – namiary na dane wejściowe</li>
<li><strong>useSolrAddSchema</strong> – informacja, że dane wejściowe są w postaci Solr XML.</li>
<li><strong>stream</strong> – 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 ;))</li>
</ul>
<p>Dodatkowe parametry nie są przydatne w naszym przykładzie i opiszemy je przy innej okazji <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<h2>Ale po co to wszystko?</h2>
<p>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?</p>
<h2>Push i Pull</h2>
<p>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.</p>
<h2>Prototypowanie i testowanie zmian</h2>
<p>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.</p>
<p>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.</p>
<p>By dodać wymagane pola wykorzystaliśmy możliwość definiowania skryptów. Wcześniej zacytowany plik importu teraz wygląda tak:
</p>
<pre class="brush:xml">&lt;dataConfig&gt;
  &lt;script&gt;&lt;![CDATA[
    function CategoryPieces(row) {
      var pieces = row.get('category').split('/');
      var arr = new Array();
      for (var i=0; i &lt; 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;
  }
  ]]&gt;&lt;/script&gt;
  &lt;dataSource type="FileDataSource" /&gt;
  &lt;document&gt;
    &lt;entity
      name="document"
      processor="FileListEntityProcessor"
      baseDir="/home/import/data/2011-06-27"
      fileName=".*\.xml
<h2>Uwaga na zakończenie</h2>
<p>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.</p>
"
      recursive="false"
      rootEntity="false"
      dataSource="null"&gt;
      &lt;entity
        processor="XPathEntityProcessor"
        url="
<h2>Objaśnienie przykładu</h2>
<p>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:
</p>
<pre wp-pre-tag-1=""></pre>
<p>dodatkowe, nieobowiązkowe atrybuty są w zasadzie oczywiste:</p>
<ul>
<li><strong>basePath</strong> – podaje katalog względem którego będzie określane położenie plików podane w tagu „entity”</li>
<li><strong>encoding</strong> – określa kodowanie plików (domyślnie: kodowanie domyślne systemu)</li>
</ul>
<p>Po definicji źródła następuje definicja dokumentu z dwoma, zagnieżdżonymi opisami encji.</p>
<p>Zadaniem głównej encji jest wygenerowanie listy plików. Do tego celu wykorzystywany jest <strong>FileListEntityProcessor</strong>. Encja jest w zasadzie samowystarczalna i do jej działania nie jest potrzebne żadne źródło danych (dlatego: dataSource=”null”). Atrybuty wykorzystywane to:</p>
<ul>
<li><strong>fileName</strong> (wymagane) – wyrażenie regularne, określające które pliki należy pobrać</li>
<li><strong>recursive</strong> – czy pliki szukane będą również w podkatalogach (domyślnie: nie)</li>
<li><strong>rootEntity</strong> – 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.</li>
<li><strong>baseDir</strong> (wymagane) katalog, w którym poszukiwane będą pliki</li>
<li><strong>dataSource</strong> – w tym wypadku „null”, gdyż encja nie korzysta z żadnego źródła. (W zasadzie w solr &gt; 1.3 parametr ten można po prostu pominąć)</li>
<li><strong>excludes</strong> – wyrażenie regularne określające, które pliki pominąć przy wyszukiwaniu</li>
<li><strong>newerThan</strong> – 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ę</li>
<li><strong>olderThan</strong> – jw. tylko dla starszych plików</li>
<li><strong>biggerThan</strong> – określa rozmiar pliku – tylko większe pliki będą brane pod uwagę</li>
<li><strong>smallerThan</strong> – jw. dla mniejszych plików</li>
</ul>
<p>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: <strong>XpathEntityProcessor</strong> używany do plików XML rozpoznaje następujące atrybuty:</p>
<ul>
<li><strong>url</strong> – namiary na dane wejściowe</li>
<li><strong>useSolrAddSchema</strong> – informacja, że dane wejściowe są w postaci Solr XML.</li>
<li><strong>stream</strong> – 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 ;))</li>
</ul>
<p>Dodatkowe parametry nie są przydatne w naszym przykładzie i opiszemy je przy innej okazji <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<h2>Ale po co to wszystko?</h2>
<p>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?</p>
<h2>Push i Pull</h2>
<p>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.</p>
<h2>Prototypowanie i testowanie zmian</h2>
<p>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.</p>
<p>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.</p>
<p>By dodać wymagane pola wykorzystaliśmy możliwość definiowania skryptów. Wcześniej zacytowany plik importu teraz wygląda tak:
</p>
<pre wp-pre-tag-2=""></pre>
<h2>Uwaga na zakończenie</h2>
<p>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.</p>
<p>{document.fileAbsolutePath}"<br />
        useSolrAddSchema="true"<br />
        stream="true"&gt;<br />
      &lt;/entity&gt;<br />
    &lt;/entity&gt;<br />
  &lt;/document&gt;<br />
&lt;/dataConfig&gt;</p>
<h2>Objaśnienie przykładu</h2>
<p>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:
</p>
<pre wp-pre-tag-1=""></pre>
<p>dodatkowe, nieobowiązkowe atrybuty są w zasadzie oczywiste:</p>
<ul>
<li><strong>basePath</strong> – podaje katalog względem którego będzie określane położenie plików podane w tagu „entity”</li>
<li><strong>encoding</strong> – określa kodowanie plików (domyślnie: kodowanie domyślne systemu)</li>
</ul>
<p>Po definicji źródła następuje definicja dokumentu z dwoma, zagnieżdżonymi opisami encji.</p>
<p>Zadaniem głównej encji jest wygenerowanie listy plików. Do tego celu wykorzystywany jest <strong>FileListEntityProcessor</strong>. Encja jest w zasadzie samowystarczalna i do jej działania nie jest potrzebne żadne źródło danych (dlatego: dataSource=”null”). Atrybuty wykorzystywane to:</p>
<ul>
<li><strong>fileName</strong> (wymagane) – wyrażenie regularne, określające które pliki należy pobrać</li>
<li><strong>recursive</strong> – czy pliki szukane będą również w podkatalogach (domyślnie: nie)</li>
<li><strong>rootEntity</strong> – 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.</li>
<li><strong>baseDir</strong> (wymagane) katalog, w którym poszukiwane będą pliki</li>
<li><strong>dataSource</strong> – w tym wypadku „null”, gdyż encja nie korzysta z żadnego źródła. (W zasadzie w solr &gt; 1.3 parametr ten można po prostu pominąć)</li>
<li><strong>excludes</strong> – wyrażenie regularne określające, które pliki pominąć przy wyszukiwaniu</li>
<li><strong>newerThan</strong> – 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ę</li>
<li><strong>olderThan</strong> – jw. tylko dla starszych plików</li>
<li><strong>biggerThan</strong> – określa rozmiar pliku – tylko większe pliki będą brane pod uwagę</li>
<li><strong>smallerThan</strong> – jw. dla mniejszych plików</li>
</ul>
<p>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: <strong>XpathEntityProcessor</strong> używany do plików XML rozpoznaje następujące atrybuty:</p>
<ul>
<li><strong>url</strong> – namiary na dane wejściowe</li>
<li><strong>useSolrAddSchema</strong> – informacja, że dane wejściowe są w postaci Solr XML.</li>
<li><strong>stream</strong> – 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 ;))</li>
</ul>
<p>Dodatkowe parametry nie są przydatne w naszym przykładzie i opiszemy je przy innej okazji <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<h2>Ale po co to wszystko?</h2>
<p>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?</p>
<h2>Push i Pull</h2>
<p>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.</p>
<h2>Prototypowanie i testowanie zmian</h2>
<p>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.</p>
<p>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.</p>
<p>By dodać wymagane pola wykorzystaliśmy możliwość definiowania skryptów. Wcześniej zacytowany plik importu teraz wygląda tak:
</p>
<pre wp-pre-tag-2=""></pre>
<h2>Uwaga na zakończenie</h2>
<p>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.</p>
<p>"<br />
      recursive="false"<br />
      rootEntity="false"<br />
      dataSource="null"&gt;<br />
      &lt;entity<br />
        processor="XPathEntityProcessor"<br />
        transformer=”script:CategoryPieces”<br />
        url="</p>
<h2>Uwaga na zakończenie</h2>
<p>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.</p>
<p>"<br />
      recursive="false"<br />
      rootEntity="false"<br />
      dataSource="null"&gt;<br />
      &lt;entity<br />
        processor="XPathEntityProcessor"<br />
        url="</p>
<h2>Objaśnienie przykładu</h2>
<p>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:
</p>
<pre wp-pre-tag-1=""></pre>
<p>dodatkowe, nieobowiązkowe atrybuty są w zasadzie oczywiste:</p>
<ul>
<li><strong>basePath</strong> – podaje katalog względem którego będzie określane położenie plików podane w tagu „entity”</li>
<li><strong>encoding</strong> – określa kodowanie plików (domyślnie: kodowanie domyślne systemu)</li>
</ul>
<p>Po definicji źródła następuje definicja dokumentu z dwoma, zagnieżdżonymi opisami encji.</p>
<p>Zadaniem głównej encji jest wygenerowanie listy plików. Do tego celu wykorzystywany jest <strong>FileListEntityProcessor</strong>. Encja jest w zasadzie samowystarczalna i do jej działania nie jest potrzebne żadne źródło danych (dlatego: dataSource=”null”). Atrybuty wykorzystywane to:</p>
<ul>
<li><strong>fileName</strong> (wymagane) – wyrażenie regularne, określające które pliki należy pobrać</li>
<li><strong>recursive</strong> – czy pliki szukane będą również w podkatalogach (domyślnie: nie)</li>
<li><strong>rootEntity</strong> – 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.</li>
<li><strong>baseDir</strong> (wymagane) katalog, w którym poszukiwane będą pliki</li>
<li><strong>dataSource</strong> – w tym wypadku „null”, gdyż encja nie korzysta z żadnego źródła. (W zasadzie w solr &gt; 1.3 parametr ten można po prostu pominąć)</li>
<li><strong>excludes</strong> – wyrażenie regularne określające, które pliki pominąć przy wyszukiwaniu</li>
<li><strong>newerThan</strong> – 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ę</li>
<li><strong>olderThan</strong> – jw. tylko dla starszych plików</li>
<li><strong>biggerThan</strong> – określa rozmiar pliku – tylko większe pliki będą brane pod uwagę</li>
<li><strong>smallerThan</strong> – jw. dla mniejszych plików</li>
</ul>
<p>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: <strong>XpathEntityProcessor</strong> używany do plików XML rozpoznaje następujące atrybuty:</p>
<ul>
<li><strong>url</strong> – namiary na dane wejściowe</li>
<li><strong>useSolrAddSchema</strong> – informacja, że dane wejściowe są w postaci Solr XML.</li>
<li><strong>stream</strong> – 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 ;))</li>
</ul>
<p>Dodatkowe parametry nie są przydatne w naszym przykładzie i opiszemy je przy innej okazji <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<h2>Ale po co to wszystko?</h2>
<p>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?</p>
<h2>Push i Pull</h2>
<p>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.</p>
<h2>Prototypowanie i testowanie zmian</h2>
<p>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.</p>
<p>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.</p>
<p>By dodać wymagane pola wykorzystaliśmy możliwość definiowania skryptów. Wcześniej zacytowany plik importu teraz wygląda tak:
</p>
<pre wp-pre-tag-2=""></pre>
<h2>Uwaga na zakończenie</h2>
<p>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.</p>
<p>{document.fileAbsolutePath}"<br />
        useSolrAddSchema="true"<br />
        stream="true"&gt;<br />
      &lt;/entity&gt;<br />
    &lt;/entity&gt;<br />
  &lt;/document&gt;<br />
&lt;/dataConfig&gt;</p>
<h2>Objaśnienie przykładu</h2>
<p>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:
</p>
<pre wp-pre-tag-1=""></pre>
<p>dodatkowe, nieobowiązkowe atrybuty są w zasadzie oczywiste:</p>
<ul>
<li><strong>basePath</strong> – podaje katalog względem którego będzie określane położenie plików podane w tagu „entity”</li>
<li><strong>encoding</strong> – określa kodowanie plików (domyślnie: kodowanie domyślne systemu)</li>
</ul>
<p>Po definicji źródła następuje definicja dokumentu z dwoma, zagnieżdżonymi opisami encji.</p>
<p>Zadaniem głównej encji jest wygenerowanie listy plików. Do tego celu wykorzystywany jest <strong>FileListEntityProcessor</strong>. Encja jest w zasadzie samowystarczalna i do jej działania nie jest potrzebne żadne źródło danych (dlatego: dataSource=”null”). Atrybuty wykorzystywane to:</p>
<ul>
<li><strong>fileName</strong> (wymagane) – wyrażenie regularne, określające które pliki należy pobrać</li>
<li><strong>recursive</strong> – czy pliki szukane będą również w podkatalogach (domyślnie: nie)</li>
<li><strong>rootEntity</strong> – 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.</li>
<li><strong>baseDir</strong> (wymagane) katalog, w którym poszukiwane będą pliki</li>
<li><strong>dataSource</strong> – w tym wypadku „null”, gdyż encja nie korzysta z żadnego źródła. (W zasadzie w solr &gt; 1.3 parametr ten można po prostu pominąć)</li>
<li><strong>excludes</strong> – wyrażenie regularne określające, które pliki pominąć przy wyszukiwaniu</li>
<li><strong>newerThan</strong> – 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ę</li>
<li><strong>olderThan</strong> – jw. tylko dla starszych plików</li>
<li><strong>biggerThan</strong> – określa rozmiar pliku – tylko większe pliki będą brane pod uwagę</li>
<li><strong>smallerThan</strong> – jw. dla mniejszych plików</li>
</ul>
<p>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: <strong>XpathEntityProcessor</strong> używany do plików XML rozpoznaje następujące atrybuty:</p>
<ul>
<li><strong>url</strong> – namiary na dane wejściowe</li>
<li><strong>useSolrAddSchema</strong> – informacja, że dane wejściowe są w postaci Solr XML.</li>
<li><strong>stream</strong> – 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 ;))</li>
</ul>
<p>Dodatkowe parametry nie są przydatne w naszym przykładzie i opiszemy je przy innej okazji <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<h2>Ale po co to wszystko?</h2>
<p>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?</p>
<h2>Push i Pull</h2>
<p>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.</p>
<h2>Prototypowanie i testowanie zmian</h2>
<p>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.</p>
<p>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.</p>
<p>By dodać wymagane pola wykorzystaliśmy możliwość definiowania skryptów. Wcześniej zacytowany plik importu teraz wygląda tak:
</p>
<pre wp-pre-tag-2=""></pre>
<h2>Uwaga na zakończenie</h2>
<p>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.</p>
<p>{document.fileAbsolutePath}"<br />
        useSolrAddSchema="true"<br />
        stream="true"&gt;<br />
      &lt;/entity&gt;<br />
    &lt;/entity&gt;<br />
  &lt;/document&gt;<br />
&lt;/dataConfig&gt;</p>
<h2>Uwaga na zakończenie</h2>
<p>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.</p>
<p>"<br />
      recursive="false"<br />
      rootEntity="false"<br />
      dataSource="null"&gt;<br />
      &lt;entity<br />
        processor="XPathEntityProcessor"<br />
        url="</p>
<h2>Objaśnienie przykładu</h2>
<p>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:
</p>
<pre wp-pre-tag-1=""></pre>
<p>dodatkowe, nieobowiązkowe atrybuty są w zasadzie oczywiste:</p>
<ul>
<li><strong>basePath</strong> – podaje katalog względem którego będzie określane położenie plików podane w tagu „entity”</li>
<li><strong>encoding</strong> – określa kodowanie plików (domyślnie: kodowanie domyślne systemu)</li>
</ul>
<p>Po definicji źródła następuje definicja dokumentu z dwoma, zagnieżdżonymi opisami encji.</p>
<p>Zadaniem głównej encji jest wygenerowanie listy plików. Do tego celu wykorzystywany jest <strong>FileListEntityProcessor</strong>. Encja jest w zasadzie samowystarczalna i do jej działania nie jest potrzebne żadne źródło danych (dlatego: dataSource=”null”). Atrybuty wykorzystywane to:</p>
<ul>
<li><strong>fileName</strong> (wymagane) – wyrażenie regularne, określające które pliki należy pobrać</li>
<li><strong>recursive</strong> – czy pliki szukane będą również w podkatalogach (domyślnie: nie)</li>
<li><strong>rootEntity</strong> – 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.</li>
<li><strong>baseDir</strong> (wymagane) katalog, w którym poszukiwane będą pliki</li>
<li><strong>dataSource</strong> – w tym wypadku „null”, gdyż encja nie korzysta z żadnego źródła. (W zasadzie w solr &gt; 1.3 parametr ten można po prostu pominąć)</li>
<li><strong>excludes</strong> – wyrażenie regularne określające, które pliki pominąć przy wyszukiwaniu</li>
<li><strong>newerThan</strong> – 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ę</li>
<li><strong>olderThan</strong> – jw. tylko dla starszych plików</li>
<li><strong>biggerThan</strong> – określa rozmiar pliku – tylko większe pliki będą brane pod uwagę</li>
<li><strong>smallerThan</strong> – jw. dla mniejszych plików</li>
</ul>
<p>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: <strong>XpathEntityProcessor</strong> używany do plików XML rozpoznaje następujące atrybuty:</p>
<ul>
<li><strong>url</strong> – namiary na dane wejściowe</li>
<li><strong>useSolrAddSchema</strong> – informacja, że dane wejściowe są w postaci Solr XML.</li>
<li><strong>stream</strong> – 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 ;))</li>
</ul>
<p>Dodatkowe parametry nie są przydatne w naszym przykładzie i opiszemy je przy innej okazji <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<h2>Ale po co to wszystko?</h2>
<p>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?</p>
<h2>Push i Pull</h2>
<p>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.</p>
<h2>Prototypowanie i testowanie zmian</h2>
<p>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.</p>
<p>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.</p>
<p>By dodać wymagane pola wykorzystaliśmy możliwość definiowania skryptów. Wcześniej zacytowany plik importu teraz wygląda tak:
</p>
<pre wp-pre-tag-2=""></pre>
<h2>Uwaga na zakończenie</h2>
<p>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.</p>
<p>{document.fileAbsolutePath}"<br />
        useSolrAddSchema="true"<br />
        stream="true"&gt;<br />
      &lt;/entity&gt;<br />
    &lt;/entity&gt;<br />
  &lt;/document&gt;<br />
&lt;/dataConfig&gt;</p>
<h2>Objaśnienie przykładu</h2>
<p>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:
</p>
<pre wp-pre-tag-1=""></pre>
<p>dodatkowe, nieobowiązkowe atrybuty są w zasadzie oczywiste:</p>
<ul>
<li><strong>basePath</strong> – podaje katalog względem którego będzie określane położenie plików podane w tagu „entity”</li>
<li><strong>encoding</strong> – określa kodowanie plików (domyślnie: kodowanie domyślne systemu)</li>
</ul>
<p>Po definicji źródła następuje definicja dokumentu z dwoma, zagnieżdżonymi opisami encji.</p>
<p>Zadaniem głównej encji jest wygenerowanie listy plików. Do tego celu wykorzystywany jest <strong>FileListEntityProcessor</strong>. Encja jest w zasadzie samowystarczalna i do jej działania nie jest potrzebne żadne źródło danych (dlatego: dataSource=”null”). Atrybuty wykorzystywane to:</p>
<ul>
<li><strong>fileName</strong> (wymagane) – wyrażenie regularne, określające które pliki należy pobrać</li>
<li><strong>recursive</strong> – czy pliki szukane będą również w podkatalogach (domyślnie: nie)</li>
<li><strong>rootEntity</strong> – 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.</li>
<li><strong>baseDir</strong> (wymagane) katalog, w którym poszukiwane będą pliki</li>
<li><strong>dataSource</strong> – w tym wypadku „null”, gdyż encja nie korzysta z żadnego źródła. (W zasadzie w solr &gt; 1.3 parametr ten można po prostu pominąć)</li>
<li><strong>excludes</strong> – wyrażenie regularne określające, które pliki pominąć przy wyszukiwaniu</li>
<li><strong>newerThan</strong> – 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ę</li>
<li><strong>olderThan</strong> – jw. tylko dla starszych plików</li>
<li><strong>biggerThan</strong> – określa rozmiar pliku – tylko większe pliki będą brane pod uwagę</li>
<li><strong>smallerThan</strong> – jw. dla mniejszych plików</li>
</ul>
<p>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: <strong>XpathEntityProcessor</strong> używany do plików XML rozpoznaje następujące atrybuty:</p>
<ul>
<li><strong>url</strong> – namiary na dane wejściowe</li>
<li><strong>useSolrAddSchema</strong> – informacja, że dane wejściowe są w postaci Solr XML.</li>
<li><strong>stream</strong> – 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 ;))</li>
</ul>
<p>Dodatkowe parametry nie są przydatne w naszym przykładzie i opiszemy je przy innej okazji <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<h2>Ale po co to wszystko?</h2>
<p>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?</p>
<h2>Push i Pull</h2>
<p>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.</p>
<h2>Prototypowanie i testowanie zmian</h2>
<p>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.</p>
<p>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.</p>
<p>By dodać wymagane pola wykorzystaliśmy możliwość definiowania skryptów. Wcześniej zacytowany plik importu teraz wygląda tak:
</p>
<pre wp-pre-tag-2=""></pre>
<h2>Uwaga na zakończenie</h2>
<p>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.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://solr.pl/2011/08/16/automatycznie-zapisany-szkic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Indeksowanie plików doc, pdf itp, czyli integracja Solr z  Tika</title>
		<link>https://solr.pl/2011/04/04/indeksowanie-plikow-doc-pdf-itp-czyli-integracja-solr-z-tika/</link>
					<comments>https://solr.pl/2011/04/04/indeksowanie-plikow-doc-pdf-itp-czyli-integracja-solr-z-tika/#respond</comments>
		
		<dc:creator><![CDATA[Marek Rogoziński]]></dc:creator>
		<pubDate>Mon, 04 Apr 2011 17:38:41 +0000</pubDate>
				<category><![CDATA[Solr]]></category>
		<category><![CDATA[data import handler]]></category>
		<category><![CDATA[dih]]></category>
		<guid isPermaLink="false">http://sematext.solr.pl/?p=229</guid>

					<description><![CDATA[W poprzednim artykule podaliśmy podstawowe informację, jak umożliwić przeszukiwanie &#160;zawartości plików binarnych, czyli m.in dokumentów MS Word, PDF czy LibreOffice. Dziś zrobimy to samo, wykorzystując Data Import Handler. Ponieważ parę dni temu pojawiła się nowa wersja serwera SOLR (3.1), poniższe]]></description>
										<content:encoded><![CDATA[<p>W <a title="Integracja Solr z Tika (cz 1. Podstawy)" href="http://solr.pl/2011/03/21/integracja-solr-z-tika-cz-1-podstawy/">poprzednim artykule</a> podaliśmy podstawowe informację, jak umożliwić przeszukiwanie &nbsp;zawartości plików binarnych, czyli m.in dokumentów MS Word, PDF czy LibreOffice. Dziś zrobimy to samo, wykorzystując Data Import Handler. Ponieważ parę dni temu pojawiła się nowa wersja serwera SOLR (3.1), poniższe wskazówki bazują na tej wersji. Do prezentacji wykorzystano aplikację „example” &#8211; wszystkie poniższe zmiany odnoszą się właśnie do tej aplikacji.</p>
<p><span id="more-229"></span></p>
<h2>Założenia</h2>
<p>Zakładamy, że dane dostępne są w formacie XML i zawierają podstawowe informacje o dokumencie oraz nazwę pliku w którym znajduje się treść dokumentu. Pliki znajdują się w zdefiniowanym katalogu. Przykładowy plik:
</p>
<pre class="brush:xml">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;albums&gt;
&nbsp; &nbsp; &lt;album&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;author&gt;John F.&lt;/author&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;title&gt;Life in picture&lt;/title&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;description&gt;1.jpg&lt;/description&gt;
&nbsp; &nbsp; &lt;/album&gt;
&nbsp; &nbsp; &lt;album&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;author&gt;Peter Z.&lt;/author&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;title&gt;Simple presentation&lt;/title&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;description&gt;2.pptx&lt;/description&gt;
&nbsp; &nbsp; &lt;/album&gt;
&lt;/abums&gt;</pre>
<p>Jak widać dane charakteryzują się tym, że poszczególne elementy nie mają indywidualnego identyfikatora. Ale z tym też sobie poradzimy <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /><br />
Na początku zmodyfikujemy schemat, dodając definicję pola przechowującego zawartość pliku:
</p>
<pre class="brush:xml">&lt;field name="content" type="text" indexed="true" stored="true" multiValued="true"/&gt;</pre>
<p>a w solrconfig.xml dodajemy konfigurację handlera DIH:
</p>
<pre class="brush:xml">&nbsp; &nbsp;
&lt;requestHandler name="/dataimport"&gt;
    &lt;lst name="defaults"&gt;
&nbsp;&nbsp; &nbsp;    &lt;str name="config"&gt;data-config.xml&lt;/str&gt;
&nbsp;&nbsp; &nbsp;&lt;/lst&gt;
&lt;/requestHandler&gt;</pre>
<p>Ponieważ będziemy wykorzystywać entity processor zawarty w bibliotece extras (<em>TikaEntityProcessor</em>), zmodyfikujemy również linijkę ładującą bibiliotekę DIH:
</p>
<pre class="brush:xml">&nbsp;&lt;lib dir="../../dist/" regex="apache-solr-dataimporthandler-.*\.jar" /&gt;</pre>
<p>Kolejnym krokiem jest stworzenie pliku data-config.xml. W naszym przypadku:
</p>
<pre class="brush:xml">&lt;dataConfig&gt;
&nbsp; &nbsp; &lt;script&gt;&lt;![CDATA[
&nbsp; &nbsp; &nbsp; &nbsp; id = 1;
        function GenerateId(row) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row.put('id', (id ++).toFixed());
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return row;
&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp;
       ]]&gt;&lt;/script&gt;
   &lt;dataSource type="BinURLDataSource" name="data"/&gt;
&nbsp; &nbsp; &lt;dataSource type="URLDataSource" baseUrl="http://localhost/tmp/bin/" name="main"/&gt;
&nbsp; &nbsp; &lt;document&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;entity name="rec" processor="XPathEntityProcessor" url="data.xml" forEach="/albums/album" dataSource="main" transformer="script:GenerateId"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field column="title" xpath="//title" /&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field column="description" xpath="//description" /&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;entity processor="TikaEntityProcessor" url="http://localhost/tmp/bin/
<h2>Generowanie identyfikatora rekordu - skrypty</h2>
<p>Pierwszym ciekawym elementem jest wykorzystanie standardowo dostępnego <em>ScriptTransformera</em> w celu wygenerowania identyfikatorów dokumentów. Dzięki metodzie javascript „<em>GenerateId</em>” oraz odwołania do niej (<em>transformer="script:GenerateId"</em>)każdy rekord będzie dodatkowo ponumerowany. Szczerze mówiąc nie jest to zbyt dobra metoda na radzenie sobie z brakiem identyfikatorów, bo nie pozwala na indeksowanie przyrostowe (nie jesteśmy w stanie rozróżnić poszczególnych wersji rekordu) – użyto jej tutaj tylko i wyłącznie w celu pokazania jak łatwo modyfikować poszczególne rekordy. Jeśli nie lubisz Javascriptu – możesz użyć dowolnego języka skryptowego wspieranego przez Java6.</p>
<h2>Wykorzystanie wielu źródeł danych</h2>
<p>Drugim ciekawym elementem jest wykorzystanie kilku źródeł danych. Ponieważ nasze metadane są dostępne w pliku XML, konieczne jest pobranie tego pliku. Postępujemy standardowo : definiujemy <em>UrlDataSource</em> a następnie przy pomocy processora <em>XpathEntityProcessor</em> analizujemy przychodzące dane.&nbsp;Ponieważ dodatkowo musimy pobrać binarne załączniki do każdego rekordu, definiujemy dodatkowe źródło: &nbsp;<em>BinURLDataSource</em> oraz dodatkowe entity, korzystające z procesora &nbsp;<em>TikaEntityProcessor</em>. Jeszcze tylko powiadomienie entity skąd pobrać plik (atrybut url z odwołaniem się do entity – rodzica) oraz powiadomienie z którego źródła skorzystać (atrybut <em>dataSource</em>). Całość dopełnia lista pól do zindeksowania (dodatkowy atrybut <em>meta</em> oznacza, że dane są pobierane z metadanych pliku).</p>
<h2>Dostępne pola</h2>
<p>Apache Tika pozwala na pobranie z dokumentu szeregu dodatkowych danych. W przykładzie powyżej skorzystaliśmy tylko z tytułu, autora i treści dokumentu. Pełne informacje o dostępnych polach są zawarte w interfejsach, które są implementowane przez klasę <em>Metadata</em> ( <a href="http://tika.apache.org/0.9/api/org/apache/tika/metadata/Metadata.html">http://tika.apache.org/0.9/api/org/apache/tika/metadata/Metadata.html</a>)a dokładnie w stałych definiowanych w tych interfejsach. W szczególności interesujące są <em>DublinCore</em> i <em>MSOffice</em></p>
<h2>Zakończenie</h2>
<p>Po uruchomieniu solr i rozpoczęciu procesu importu (czyli wywołania adresu: <em>http://localhost:8983/solr/dataimport?command=full-import</em>) po krótkiej chwili dokumenty zostają wczytane co powinno być widoczne po zadaniu zapytania:<em>http://localhost:8983/solr/select?q=*:*</em></p>
{rec.description}" dataSource="data"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field column="text" name="content" /&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field column="Author" name="author" meta="true" /&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field column="title" name="title" meta="true" /&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/entity&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;/entity&gt;
&nbsp; &nbsp; &lt;/document&gt;
&lt;/dataConfig&gt;</pre>
<h2>Generowanie identyfikatora rekordu &#8211; skrypty</h2>
<p>Pierwszym ciekawym elementem jest wykorzystanie standardowo dostępnego <em>ScriptTransformera</em> w celu wygenerowania identyfikatorów dokumentów. Dzięki metodzie javascript „<em>GenerateId</em>” oraz odwołania do niej (<em>transformer=&#8221;script:GenerateId&#8221;</em>)każdy rekord będzie dodatkowo ponumerowany. Szczerze mówiąc nie jest to zbyt dobra metoda na radzenie sobie z brakiem identyfikatorów, bo nie pozwala na indeksowanie przyrostowe (nie jesteśmy w stanie rozróżnić poszczególnych wersji rekordu) – użyto jej tutaj tylko i wyłącznie w celu pokazania jak łatwo modyfikować poszczególne rekordy. Jeśli nie lubisz Javascriptu – możesz użyć dowolnego języka skryptowego wspieranego przez Java6.</p>
<h2>Wykorzystanie wielu źródeł danych</h2>
<p>Drugim ciekawym elementem jest wykorzystanie kilku źródeł danych. Ponieważ nasze metadane są dostępne w pliku XML, konieczne jest pobranie tego pliku. Postępujemy standardowo : definiujemy <em>UrlDataSource</em> a następnie przy pomocy processora <em>XpathEntityProcessor</em> analizujemy przychodzące dane.&nbsp;Ponieważ dodatkowo musimy pobrać binarne załączniki do każdego rekordu, definiujemy dodatkowe źródło: &nbsp;<em>BinURLDataSource</em> oraz dodatkowe entity, korzystające z procesora &nbsp;<em>TikaEntityProcessor</em>. Jeszcze tylko powiadomienie entity skąd pobrać plik (atrybut url z odwołaniem się do entity – rodzica) oraz powiadomienie z którego źródła skorzystać (atrybut <em>dataSource</em>). Całość dopełnia lista pól do zindeksowania (dodatkowy atrybut <em>meta</em> oznacza, że dane są pobierane z metadanych pliku).</p>
<h2>Dostępne pola</h2>
<p>Apache Tika pozwala na pobranie z dokumentu szeregu dodatkowych danych. W przykładzie powyżej skorzystaliśmy tylko z tytułu, autora i treści dokumentu. Pełne informacje o dostępnych polach są zawarte w interfejsach, które są implementowane przez klasę <em>Metadata</em> ( <a href="http://tika.apache.org/0.9/api/org/apache/tika/metadata/Metadata.html">http://tika.apache.org/0.9/api/org/apache/tika/metadata/Metadata.html</a>)a dokładnie w stałych definiowanych w tych interfejsach. W szczególności interesujące są <em>DublinCore</em> i <em>MSOffice</em></p>
<h2>Zakończenie</h2>
<p>Po uruchomieniu solr i rozpoczęciu procesu importu (czyli wywołania adresu: <em>http://localhost:8983/solr/dataimport?command=full-import</em>) po krótkiej chwili dokumenty zostają wczytane co powinno być widoczne po zadaniu zapytania:<em>http://localhost:8983/solr/select?q=*:*</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://solr.pl/2011/04/04/indeksowanie-plikow-doc-pdf-itp-czyli-integracja-solr-z-tika/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Data Import Handler &#038; XML &#8211; zagnieżdzone encje</title>
		<link>https://solr.pl/2011/03/07/data-import-handler-xml-zagniezdzone-encje/</link>
					<comments>https://solr.pl/2011/03/07/data-import-handler-xml-zagniezdzone-encje/#respond</comments>
		
		<dc:creator><![CDATA[Marek Rogoziński]]></dc:creator>
		<pubDate>Mon, 07 Mar 2011 08:12:53 +0000</pubDate>
				<category><![CDATA[Solr]]></category>
		<category><![CDATA[data import handler]]></category>
		<category><![CDATA[dih]]></category>
		<category><![CDATA[import]]></category>
		<category><![CDATA[solr]]></category>
		<guid isPermaLink="false">http://sematext.solr.pl/?p=205</guid>

					<description><![CDATA[Data Import Handler jest bardzo miłym i rozbudowanym narzędziem. Poniżej opis problemu (i rozwiązania) w którym spotkałem się ostatnio. Opis Problemu Do zaindeksowania jest pewna lista produktów. Produkty jednak mogą być łączone w grupy. Dodatkowo w grupie, w kolejnych elementach]]></description>
										<content:encoded><![CDATA[<p>Data Import Handler jest bardzo miłym i rozbudowanym narzędziem. Poniżej opis problemu (i rozwiązania) w którym spotkałem się ostatnio.</p>
<p><span id="more-205"></span></p>
<h2>Opis Problemu</h2>
<p>Do zaindeksowania jest pewna lista produktów. Produkty jednak mogą być łączone w grupy. Dodatkowo w grupie, w kolejnych elementach mogą być pominięte te dane, które w elemencie wcześniej zostały zdefiniowane. Przykładowa struktura (nieistotne informacje pominąłem dla czytelności):
</p>
<pre class="brush:xml">&lt;products&gt;
  &lt;product&gt;
    &lt;id&gt;1&lt;/id&gt;
    &lt;name&gt;Product 1&lt;/name&gt;
  &lt;/product&gt;
  &lt;product&gt;
    &lt;id&gt;2&lt;/id&gt;
    &lt;name&gt;Product 2&lt;/name&gt;
  &lt;/product&gt;
  &lt;group&gt;
    &lt;product&gt;
      &lt;id&gt;3&lt;/id&gt;
      &lt;name&gt;Product 3 and 4&lt;/name&gt;
    &lt;/product&gt;
    &lt;product&gt;
      &lt;id&gt;4&lt;/id&gt;
    &lt;/product&gt;
  &lt;/group&gt;
&lt;/products&gt;</pre>
<h2>Rozwiązanie</h2>
<p>Rozwiązanie polega na zdefiniowaniu &#8211; jak zawszę &#8211; elementu &#8222;entity&#8221; w sposób następujący:
</p>
<pre class="brush:xml">&lt;entity processor="XPathEntityProcessor"
    forEach="/products/product | /products/group/product"&gt;
  &lt;field column="id" xpath="//id" /&gt;
  &lt;field column="name" xpath="//name" commonField="true" /&gt;
&lt;/entity&gt;</pre>
<h2>Wyjaśnienie</h2>
<p>Dzięki takiej konstrukcji &#8222;forEach&#8221; do przetworzenia dostaną się zarówno produkty nie należące do grupy, jak i te w grupach. Istotnym atrybutem pola jest &#8222;commonField&#8221;. Informuje on DIH, że jeśli w danym rekordzie nie jest zdefiniowane to pole, należy je pobrać z rekordu poprzedniego.</p>
<p>Podane rozwiązanie ma parę ograniczeń, np. pierwszy element w grupie powinien mieć zdefiniowane pole &#8222;name&#8221; oraz ważna jest kolejność produktów, natomiast w moim przypadku pokrywało się to dokładnie ze specyfikacją dostarczonego pliku importu.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://solr.pl/2011/03/07/data-import-handler-xml-zagniezdzone-encje/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Data Import Handler – usuwanie danych z indeksu</title>
		<link>https://solr.pl/2011/01/03/data-import-handler-usuwanie-danych-z-indeksu/</link>
					<comments>https://solr.pl/2011/01/03/data-import-handler-usuwanie-danych-z-indeksu/#respond</comments>
		
		<dc:creator><![CDATA[Marek Rogoziński]]></dc:creator>
		<pubDate>Mon, 03 Jan 2011 07:58:02 +0000</pubDate>
				<category><![CDATA[Solr]]></category>
		<category><![CDATA[baza danych]]></category>
		<category><![CDATA[data import handler]]></category>
		<category><![CDATA[dih]]></category>
		<category><![CDATA[import]]></category>
		<category><![CDATA[integracja]]></category>
		<guid isPermaLink="false">http://sematext.solr.pl/?p=171</guid>

					<description><![CDATA[Usuwanie danych z indeksu przy wykorzystaniu indeksowania przyrostowego w DIH jest na wiki SOLR potraktowane szczątkowo, jako coś, co działa analogicznie do aktualizacji rekordów. Podobnie we wcześniejszym artykule użyłem tego skrótu, tym bardziej, że podany przeze mnie przykład z indeksowaniem]]></description>
										<content:encoded><![CDATA[<p>Usuwanie danych z indeksu przy wykorzystaniu indeksowania przyrostowego w DIH jest na wiki SOLR potraktowane szczątkowo, jako coś, co działa analogicznie do aktualizacji rekordów. Podobnie we wcześniejszym artykule użyłem tego skrótu, tym bardziej, że podany przeze mnie przykład z indeksowaniem zasobów wikipedii nie potrzebował usuwania danych.</p>
<p><span id="more-171"></span></p>
<p>Mając pod ręką przykładowe dane z albumami i wykonawcami postanowiłem pokazać mój sposób postępowania w takich wypadkach. Dla uproszczenia i przejrzystości zakładam, że po pierwszym zaimportowaniu, danych może tylko ubywać.</p>
<h2>Dane testowe</h2>
<p>Moje dane testowe mieszczą się bazie PostgreSQL w tabeli zdefiniowanej następująco:</p>
<pre>Table "public.albums"
Column |  Type   |                      Modifiers
--------+---------+-----------------------------------------------------
id     | integer | not null default nextval('albums_id_seq'::regclass)
name   | text    | not null
author | text    | not null
Indexes:
"albums_pk" PRIMARY KEY, btree (id)</pre>
<p>W tabeli znajduje się 825661 rekordów.</p>
<h2>Instalacja testowa</h2>
<p>Do testów użyłem instancji SOLR posiadającej następującą charakterystykę:</p>
<p>Definicja w schema.xml:</p>
<pre class="brush:xml">&lt;fields&gt;
&lt;field name="id" type="string" indexed="true" stored="true" required="true" /&gt;
&lt;field name="album" type="text" indexed="true" stored="true" multiValued="true"/&gt;
&lt;field name="author" type="text" indexed="true" stored="true" multiValued="true"/&gt;
&lt;/fields&gt;
&lt;uniqueKey&gt;id&lt;/uniqueKey&gt;
&lt;defaultSearchField&gt;album&lt;/defaultSearchField&gt;</pre>
<p>Definicja DIH w solrconfig.xml:</p>
<pre class="brush:xml">&lt;requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler"&gt;
&lt;lst name="defaults"&gt;
&lt;str name="config"&gt;db-data-config.xml&lt;/str&gt;
&lt;/lst&gt;
&lt;/requestHandler&gt;</pre>
<p>I plik DIH db-data-config.xml:</p>
<pre class="brush:xml">&lt;dataConfig&gt;
&lt;dataSource driver="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/shardtest" user="solr" password="secret" /&gt;
&lt;document&gt;
&lt;entity name="album" query="SELECT * from albums"&gt;
&lt;field column="id" name="id" /&gt;
&lt;field column="name" name="album" /&gt;
&lt;field column="author" name="author" /&gt;
&lt;/entity&gt;
&lt;/document&gt;
&lt;/dataConfig&gt;</pre>
<p>Przed naszym testem zaimportowałem wszystkie dane z tabeli <em>albums</em>.</p>
<h2>Usuwanie danych</h2>
<p>Patrząc na tabelę widać, że gdy usuniemy rekord, ginie on bez śladu i jedynym sposobem aktualizacji naszego indeksu byłoby porównanie identyfikatorów dokumentów w indeksie z identyfikatorami w bazie i wyrzucenie tych, które w bazie już nie istnieją. Wolne i niewygodne. Innym sposobem jest dodatnie kolumny <em>deleted_at</em>: zamiast kasowania fizycznie rekordu, uzupełniamy tylko tę kolumnę. DIH może wtedy pobrać wszystkie rekordy z ustawioną datą późniejszą od ostatniego indeksowania. Wadą tego rozwiązania może by konieczność modyfikacji aplikacji by uwzględniały tak „skasowane” rekordy.</p>
<p>Ja zastosuje inne rozwiązanie, przeźroczyste dla aplikacji. Tworzymy nową tabelę:</p>
<pre class="brush:sql">CREATE TABLE deletes
(
id serial NOT NULL,
deleted_id bigint,
deleted_at timestamp without time zone NOT NULL,
CONSTRAINT deletes_pk PRIMARY KEY (id)
);</pre>
<p>Do tej tabeli automagicznie będziemy dopisywać identyfikatory tych elementów, które zostały usunięte z tabeli <em>albums</em> oraz informacje kiedy zostały usunięte.</p>
<p>Teraz dodamy jeszcze funkcję:</p>
<pre class="brush:sql">CREATE OR REPLACE FUNCTION insert_after_delete()
RETURNS trigger AS
$BODY$BEGIN
IF tg_op = 'DELETE' THEN
INSERT INTO deletes(deleted_id, deleted_at)
VALUES (old.id, now());
RETURN old;
END IF;
END$BODY$
LANGUAGE plpgsql VOLATILE;</pre>
<p>oraz trigger:</p>
<pre class="brush:sql">CREATE TRIGGER deleted_trg
BEFORE DELETE
ON albums
FOR EACH ROW
EXECUTE PROCEDURE insert_after_delete();</pre>
<h2>Sprawdzamy działanie</h2>
<p>Zgodnie z planem, każdy usunięty wpis w tabeli <em>albums</em> powinien skutkować uzupełnieniem tabeli<br /><em>deletes</em>. Sprawdźmy więc. Usuwamy parę rekordów:</p>
<pre class="brush:sql">=&gt; DELETE FROM albums where id &lt; 37;
DELETE 2
=&gt; SELECT * from deletes;
id | deleted_id |         deleted_at
----+------------+----------------------------
26 |         35 | 2010-12-23 13:53:18.034612
27 |         36 | 2010-12-23 13:53:18.034612
(2 rows)</pre>
<p>Czyli baza działa.</p>
<p>Uzupełniamy plik konfiguracyjny DIH tak, by <em>entity</em> było zdefiniowane następująco:</p>
<pre class="brush:xml">&lt;entity name="album" query="SELECT * from albums"
  deletedPkQuery="SELECT deleted_id as id FROM deletes WHERE deleted_at &gt; '$'{dataimporter.last_index_time}'"&gt;</pre>
<p>Dzięki temu przy imporcie przyrostowym DIH użyje atrybutu <em>deletedPkQuery</em> by pobrać identyfikatory tych dokumentów, które należy usunąć.</p>
<p>Sprytny czytelnik pewnie zacznie się zastanawiać, czy na pewno potrzebna jest nam kolumna z datą usunięcia rekordu. Przecież możemy usunąć wszystkie rekordy znalezione w tabeli <em>deleted</em> a następnie skasować zawartość tej tabeli. Teoretycznie to prawda, ale w przypadku problemu z serwerem indeksującym SOLR w naszym wypadku łatwo zastąpić go innym – jego stopień synchronizacji z bazą nie jest bardzo istotny – po prostu za następnym importem przyrostowym nastąpi synchronizacja z bazą. W opcji z kasowaniem zawartości <em>deletes</em> takie możliwości nie ma.</p>
<p>Wykonujemy teraz import przyrostowy wywołując adres: <em>/solr/dataimport?command=delta-import</em><br />W logach powinna pojawić się linia podobna do tej:<br /><em>INFO: {delete=[35, 36],optimize=} 0 2</em><br />Co oznacza, że DIH poprawnie usunął z indeksu te dokumenty, które usunęliśmy wcześniej z bazy.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://solr.pl/2011/01/03/data-import-handler-usuwanie-danych-z-indeksu/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Data Import Handler – sharding</title>
		<link>https://solr.pl/2010/12/27/data-import-handler-sharding/</link>
					<comments>https://solr.pl/2010/12/27/data-import-handler-sharding/#respond</comments>
		
		<dc:creator><![CDATA[Marek Rogoziński]]></dc:creator>
		<pubDate>Mon, 27 Dec 2010 07:57:08 +0000</pubDate>
				<category><![CDATA[Solr]]></category>
		<category><![CDATA[baza danych]]></category>
		<category><![CDATA[data import handler]]></category>
		<category><![CDATA[dih]]></category>
		<category><![CDATA[integracja]]></category>
		<guid isPermaLink="false">http://sematext.solr.pl/?p=169</guid>

					<description><![CDATA[Nasza czytelniczka (pozdrawiamy!) zgłosiła się do nas z problemem dotyczącym współpracy DIH z shardingiem. Wiki projektu SOLR pokazuje moim zdaniem rozwiązanie tej kwestii, ale czyni to trochę na około i przy okazji. Co to jest sharding? Sharding oznacza podział danych]]></description>
										<content:encoded><![CDATA[<p>Nasza czytelniczka (pozdrawiamy!) zgłosiła się do nas z problemem dotyczącym współpracy DIH z shardingiem. Wiki projektu SOLR pokazuje moim zdaniem rozwiązanie tej kwestii, ale czyni to trochę na około i przy okazji.</p>
<p><span id="more-169"></span></p>
<h2>Co to jest sharding?</h2>
<p>Sharding oznacza podział danych na kilka części oraz przechowywanie i obróbkę tych danych niezależnie. Dodatkowa logika w ramach aplikacji pozwala na wybranie odpowiedniej części zbioru danych i/lub łączenie wyników z poszczególnych źródeł. W przypadku DIH i shardingu możemy mieć do czynienia z następującym przypadkiem:</p>
<ul>
<li>sharding po stronie źródło danych – 	czyli wiele lokalizacji / tabel zawierających poszczególne części 	zbioru danych</li>
<li>sharding po stronie SOLR – czyli 	podzielenie danych ze źródła na wiele niezależnych instancji 	SOLR</li>
<li>oba powyższe jednocześnie</li>
</ul>
<p>W opisywanym przypadku mamy jeden zbiór danych i chcemy stworzyć wiele zbiorów (tzw. shardów) po stronie SOLR.</p>
<h2>Kiedy stosować sharding?</h2>
<p>Bardzo ważna kwestia: <strong>po co?</strong> W moim mniemaniu sharding bywa zbyt często nadużywany generując mnóstwo dodatkowych komplikacji i ograniczeń. Główny powód to duży wolumen danych, które<strong> </strong>powodują, że indeks SOLR <strong>nie mieści się w obrębie jednej maszyny</strong>. Jeśli tak nie jest – często oznacza to, że sharding jest zbędny. Kolejny powód to wydajność. Jednak sharding może tutaj pomóc tylko wtedy, gdy inne optymalizacje zawiodą a zapytania są na tyle skomplikowane, że sam narzut shardingu (przekazania zapytania do poszczególnych shardów i łączenie ich odpowiedzi) jest mniejszy niż zysk możliwy do uzyskania.</p>
<h2>Dane testowe</h2>
<p>Zakładamy jednak, że sharding jest nam potrzebny. W przykładzie poniżej użyłem danych z musicbrainz tworząc prostą tabelę postgresową:
</p>
<pre>Table "public.albums"</pre>
<pre> Column |  Type   |                      Modifiers
--------+---------+-----------------------------------------------------</pre>
<pre> id     | integer | not null default nextval('albums_id_seq'::regclass)</pre>
<pre> name   | text    | not null</pre>
<pre> author | text    | not null</pre>
<pre>Indexes:</pre>
<pre>"albums_pk" PRIMARY KEY, btree (id)</pre>
<p>W tabeli znajduje się 825661 rekordów. Podkreślam tutaj, że zarówno struktura jak i ilość danych jest na tyle małe, że praktyczna przydatność shardingu jest tu pomijalna.</p>
<h2>Instalacja testowa</h2>
<p>Do testów użyjemy trzech instancji SOLR. Wszystkie instancje są identyczne, różnica jest związana tylko z numerem portów (8983, 7872, 6761) – testy będą wykonywane na jednej fizycznej maszynie.</p>
<p>Definicja w schema.xml:
</p>
<pre class="brush:xml">&lt;fields&gt;
 &lt;field name="id" type="string" indexed="true" stored="true" required="true" /&gt;
 &lt;field name="album" type="text" indexed="true" stored="true" multiValued="true"/&gt;
 &lt;field name="author" type="text" indexed="true" stored="true" multiValued="true"/&gt;
&lt;/fields&gt;
&lt;uniqueKey&gt;id&lt;/uniqueKey&gt;
&lt;defaultSearchField&gt;album&lt;/defaultSearchField&gt;</pre>
<p>Definicja DIH w solrconfig.xml:
</p>
<pre class="brush:xml">&lt;requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler"&gt;
 &lt;lst name="defaults"&gt;
  &lt;str name="config"&gt;db-data-config.xml&lt;/str&gt;
 &lt;/lst&gt;
&lt;/requestHandler&gt;</pre>
<p>I plik DIH db-data-config.xml:
</p>
<pre class="brush:xml">&lt;dataConfig&gt;
 &lt;dataSource driver="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/shardtest" user="solr" password="secret" /&gt;
 &lt;document&gt;
  &lt;entity name="album" query="SELECT * from albums"&gt;
   &lt;field column="id" name="id" /&gt;
   &lt;field column="name" name="album" /&gt;
   &lt;field column="author" name="author" /&gt;
  &lt;/entity&gt;
 &lt;/document&gt;
&lt;/dataConfig&gt;</pre>
<p>W tym momencie każda instancja jest w stanie dokonać pełnego importu danych.</p>
<h2>Zestawiamy sharding</h2>
<p>Naszym celem jest takie zmodyfikowanie konfiguracji DIH by każda instancja indeksowała tylko „swoją” część danych. Najprościej zrobić to modyfikując zapytanie pobierające dane np w ten sposób:</p>
<p>SELECT * from albums where id % LICZBA_INSTANCJI = NUMER_INSTANCJI</p>
<p>gdzie:</p>
<ul>
<li>LICZBA_INSTANCJI 	– liczba serwerów SOLR przechowujących unikalne części zbioru 	danych</li>
<li>NUMER_INSTANCJI – 	numer instancji (liczony od zera)</li>
</ul>
<p>takie zapytanie nie gwarantuje nam dokładnie i idealnie równego podziału ale spełnia dwa konieczne warunki:</p>
<ul>
<li>dany rekord 	trafi zawsze na konkretną i <strong>zawszę tę samą</strong> instancję</li>
<li>pojedynczy 	rekord trafi zawsze na tylko <strong>jedną</strong> instancję</li>
</ul>
<p>czyli  db-data-config.xml  na każdej maszynie różni się teraz zapytaniem i wygląda na poszczególnych instancjach następująco:</p>
<ul>
<li>SELECT * from albums where id % 3 = 0</li>
<li>SELECT * from albums where id % 3 = 1</li>
<li>SELECT * from albums where id % 3 = 2</li>
</ul>
<h2>Sprawdzamy działanie</h2>
<p>Po uruchomieniu wszystkich instancji SOLR na każdej wywołujemy adres:</p>
<p><em>/solr/dataimport?command=full-import</em></p>
<p>Po zakończeniu pracy DIH i wywołaniu:</p>
<p><em> /solr/dataimport?command=status</em></p>
<p>dostajemy w odpowiedzi od instancji odpowiednio:</p>
<ul>
<li>Added/Updated: 	275220 documents.</li>
<li>Added/Updated: 	275221 documents.</li>
<li>Added/Updated: 	275220 documents.</li>
</ul>
<p>Wykonując prostą operację dodawania widzimy, że we wszystkich instancjach łącznie mamy 825661 dokumentów, czyli tyle ile powinno tam być <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /><br />
Wykonajmy jeszcze zapytanie o wszystkie dokumenty, z wykorzystaniem shardingu wywołując na dowolnej instancji:</p>
<p><em>/solr/select/?q=*:*&amp;shards=localhost:6761/solr,localhost:7872/solr,localhost:8983/solr</em></p>
<p>Wynik:  825661.</p>
<p>To działa! <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://solr.pl/2010/12/27/data-import-handler-sharding/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Data Import Handler – import danych z baz SQL (cz. 1)</title>
		<link>https://solr.pl/2010/10/11/data-import-handler-import-danych-z-baz-sql-cz-1/</link>
					<comments>https://solr.pl/2010/10/11/data-import-handler-import-danych-z-baz-sql-cz-1/#respond</comments>
		
		<dc:creator><![CDATA[Marek Rogoziński]]></dc:creator>
		<pubDate>Mon, 11 Oct 2010 04:54:16 +0000</pubDate>
				<category><![CDATA[Solr]]></category>
		<category><![CDATA[baza danych]]></category>
		<category><![CDATA[data import handler]]></category>
		<category><![CDATA[dih]]></category>
		<category><![CDATA[import]]></category>
		<guid isPermaLink="false">http://sematext.solr.pl/?p=40</guid>

					<description><![CDATA[W artykule o sposobach importu danych (http://solr.pl/2010/09/06/solr-importowanie-danych/) wspomniałem o Data Import Handler (DIH). Podstawową zaletą tego sposobu importowania jest brak konieczności tworzenia dodatkowego oprogramowania oraz szybka integracja ze źródłem danych. Ta druga zaleta wymaga jednak wprawy i praktyki. W tym]]></description>
										<content:encoded><![CDATA[<p>W artykule o sposobach importu danych (<a href="../2010/09/06/solr-importowanie-danych/">http://solr.pl/2010/09/06/solr-importowanie-danych/</a>) wspomniałem o <strong>Data Import Handler</strong> (DIH). Podstawową zaletą tego sposobu importowania jest brak konieczności tworzenia dodatkowego oprogramowania oraz szybka integracja ze źródłem danych. Ta druga zaleta wymaga jednak wprawy i praktyki. W tym wpisie przedstawię podstawy integracji DIH ze źródłem danych SQL.</p>
<p><span id="more-40"></span></p>
<p>W przykładach użyta została baza PostgeSQL zawierająca dane polskiej wikipedii. Testowa instancja solr została zdefiniowana jako rdzeń „wikipedia” i dostępna była pod adresem:</p>
<p><a href="http://localhost:8983/solr/wikipedia/admin/">http://localhost:8983/solr/wikipedia/admin/</a></p>
<p><strong>Konfiguracja solrconfig.xml</strong></p>
<p>Konfiguracja sprowadza się do dodania dodatkowego requestHandlera. Parametr: <em>config</em> określa plik konfiguracyjny, w którym znajduje się definicja źródła danych.
</p>
<pre class="brush:xml"> &lt;requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler"&gt;
&nbsp; &lt;lst name="defaults"&gt;
&nbsp;&nbsp; &lt;str name="config"&gt;db-data-config.xml&lt;/str&gt;
&nbsp; &lt;/lst&gt;
&lt;/requestHandler&gt;</pre>
<p>Dzięki takiej definicji zyskujemy możliwość wywoływania adresu HTTP obsługującego import:</p>
<ul>
<li><em>/dataimport</em> &#8211; w celu uzyskania 	aktualnego statusu</li>
<li><em>/dataimport?command=reload-config</em> – w celu ponownego odczytania konfiguracji</li>
<li><em>/dataimport?command=full-import</em> – 	w celu zlecenia rozpoczęcia pełnego indeksowania  danych</li>
<li><em>/dataimport?command=delta-import</em> – 	w celu zlecenia rozpoczęcia indeksowania przyrostowego</li>
</ul>
<p>(dla mojej konfiguracji pełen adres to: http://localhost:8983/solr/wikipedia/dataimport)</p>
<p>Powyżej widzimy dwie możliwości importowania danych: import pełny i przyrostowy.</p>
<p><strong>Pełny import</strong> danych polega na każdorazowym wczytaniu wszystkich danych, które powinny znaleźć się w indeksie, podczas gdy <strong>import przyrostowy</strong> oznacza tylko dodanie i aktualizację w indeksie tych danych, które zmieniły się od ostatniego indeksowania. Pełny import zwykle trwa znacznie dłużej stąd prosty wniosek: jeśli czas pełnego indeksowania nie jest dla nas problemem – prawdopodobnie nie warto zawracać sobie głowy konfiguracją indeksowania przyrostowego, zwłaszcza, że nakłada ono&nbsp; dodatkowe wymagania na strukturę źródła danych.</p>
<p>Warto zaznaczyć, że pełny import domyślnie rozpoczyna się od usunięcia istniejącego indeksu.  Istnieje możliwość uniknięcia takiego zachowania poprzez dodanie  parametru: <em>clean=false</em>.</p>
<p><strong>Konfiguracja źródła danych</strong></p>
<p>Konfiguracja polega na zdefiniowaniu zapytań pozwalających solr na pobieranie danych do indeksowania i zawiera się w pliku określonym przy definicji handlera (u nas:  db-data-config.xml) W tym wpisie zaczniemy od zdefiniowania pełnego importu. Następnie, w kolejnej części artykułu rozbudujemy go o możliwość importowania przyrostowego.</p>
<p><strong>Pełny import</strong>
</p>
<pre class="brush:xml">&lt;dataConfig&gt;
&nbsp; &lt;dataSource driver="org.postgresql.Driver"
&nbsp; &nbsp;&nbsp; url="jdbc:postgresql://localhost:5432/wikipedia"
&nbsp;&nbsp;&nbsp;&nbsp; user="wikipedia"
&nbsp;&nbsp;&nbsp;&nbsp; password="secret" /&gt;
&nbsp; &lt;document&gt;
&nbsp;&nbsp;&nbsp; &lt;entity name="page" query="SELECT page_id, page_title from page"&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;field column="page_id" name="id" /&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;field column="page_title" name="name" /&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;entity name="revision" query="select rev_id from revision where rev_page=${page.page_id}"&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;entity name="pagecontent" query="select old_text from pagecontent where old_id=${revision.rev_id}"&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;field column="old_text" name="text" /&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/entity&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/entity&gt;
&nbsp;&nbsp; &lt;/entity&gt;
&nbsp; &lt;/document&gt;
&lt;/dataConfig&gt;</pre>
<p>Jak widzimy definicja źródła składa się z opisu sposobu połączenia do baz danych oraz opisu indeksowanego dokumentu. Import następuje zgodnie z następującym algorytmem:</p>
<ol>
<li>Usuwany jest stary indeks (jeśli 	nie użyto parametru <em>clean=false</em>)</li>
<li>Solr po wywołaniu komendy 	indeksowania nawiązuje połączenie do bazy danych.</li>
<li>Definiowany jest kursor bazodanowy 	wykorzystujący zapytanie określone w argumencie „<em>query</em>” w 	głównej encji</li>
<li>Pobierana jest porcja danych</li>
<li>Dla każdego pobranego rekordu 	definiowane są zmienne postaci <em>&lt;nazwa encji&gt;.&lt;zwracana 	kolumna&gt;</em>, dzięki czemu do zwróconych wartości można odwołać 	się w encjach zagnieżdżonych</li>
<li>Wykonywane są zapytania z encji 	zagnieżdżonych</li>
<li>Encja może zawierać definicje 	pól. Dzięki temu Solr jest w stanie określić mapowanie kolumny 	z wyniku na pole dokumentu zdefiniowane w <em>schema.xml</em></li>
<li>Dokument stworzony dzięki 	wartościom zwróconych przez zapytania jest dodawany do indeksu</li>
<li>Jeśli kursor posiada kolejne 	wyniki następuje skok do punktu 4.</li>
<li>Następuje zapisanie danych do 	pliku dataimport.properties, dane zostają zatwierdzone (<em>commit</em>) i 	wykonywana jest optymalizacja indeksu</li>
</ol>
<p>Po uruchomieniu solr i wejściu na stronę:<a href="http://localhost:8983/solr/wikipedia/dataimport"> http://localhost:8983/solr/wikipedia/dataimport</a> pojawiła sie odpowiedź:
</p>
<pre class="brush:xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;response&gt;
&nbsp; &lt;lst name="responseHeader"&gt;
&nbsp;&nbsp;&nbsp; &lt;int name="status"&gt;0&lt;/int&gt;
&nbsp;&nbsp;&nbsp; &lt;int name="QTime"&gt;0&lt;/int&gt;
&nbsp; &lt;/lst&gt;
&nbsp; &lt;lst name="initArgs"&gt;
&nbsp;&nbsp;&nbsp; &lt;lst name="defaults"&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;str name="config"&gt;db-data-config.xml&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;/lst&gt;
&nbsp; &lt;/lst&gt;
&nbsp; &lt;str name="status"&gt;idle&lt;/str&gt;
&nbsp; &lt;str name="importResponse"/&gt;
&nbsp; &lt;lst name="statusMessages"/&gt;
&nbsp; &lt;str name="WARNING"&gt;This response format is experimental.  It is likely to change in the future.&lt;/str&gt;
&lt;/response&gt;</pre>
<p>Uwagę zwraca wpis: status: idle. Oznacza to, że nasz importer jest gotowy do pracy. W innym przypadku (np. Błąd poprawności XML konfiguracyjnego) dostaniemy opis wyjątku. Niestety na tym etapie nie są wykrywane jeszcze błędy związane np. z niewłaściwą definicją połączenia do bazy lub braku sterownika JDBC.</p>
<p>Wchodzimy więc na stronę:<a href="http://localhost:8983/solr/wikipedia/dataimport?command=full-import"> http://localhost:8983/solr/wikipedia/dataimport?command=full-import</a></p>
<p>To co powinniśmy otrzymać, to podobny jak wyżej XML. Jednak po ponownym wejściu na stronę:<a href="http://localhost:8983/solr/wikipedia/dataimport"> http://localhost:8983/solr/wikipedia/dataimport</a> dostajemy już inny wynik.
</p>
<pre class="brush:xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;response&gt;
&nbsp; &lt;lst name="responseHeader"&gt;
&nbsp;&nbsp;&nbsp; &lt;int name="status"&gt;0&lt;/int&gt;
&nbsp;&nbsp;&nbsp; &lt;int name="QTime"&gt;0&lt;/int&gt;
&nbsp; &lt;/lst&gt;
&nbsp; &lt;lst name="initArgs"&gt;
&nbsp;&nbsp;&nbsp; &lt;lst name="defaults"&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;str name="config"&gt;db-data-config.xml&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;/lst&gt;
&nbsp; &lt;/lst&gt;
&nbsp; &lt;str name="status"&gt;busy&lt;/str&gt;
&nbsp; &lt;str name="importResponse"&gt;A command is still running...&lt;/str&gt;
&nbsp; &lt;lst name="statusMessages"&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Time Elapsed"&gt;0:1:15.460&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Total Requests made to DataSource"&gt;39547&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Total Rows Fetched"&gt;59319&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Total Documents Processed"&gt;19772&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Total Documents Skipped"&gt;0&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Full Dump Started"&gt;2010-10-03 14:28:00&lt;/str&gt;
&nbsp; &lt;/lst&gt;
&nbsp; &lt;str name="WARNING"&gt;This response format is experimental.  It is likely to change in the future.&lt;/str&gt;
&lt;/response&gt;</pre>
<p>Czyli importer pracuje.</p>
<p>Po pewnym czasie, zależnym od ilości indeksowanych danych i szybkości komputera otrzymamy:
</p>
<pre class="brush:xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;response&gt;
&nbsp; &lt;lst name="responseHeader"&gt;
&nbsp;&nbsp;&nbsp; &lt;int name="status"&gt;0&lt;/int&gt;
&nbsp;&nbsp;&nbsp; &lt;int name="QTime"&gt;0&lt;/int&gt;
&nbsp; &lt;/lst&gt;
&nbsp; &lt;lst name="initArgs"&gt;
&nbsp;&nbsp;&nbsp; &lt;lst name="defaults"&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;str name="config"&gt;db-data-config.xml&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;/lst&gt;
&nbsp; &lt;/lst&gt;
&nbsp; &lt;str name="status"&gt;idle&lt;/str&gt;
&nbsp; &lt;str name="importResponse"/&gt;
&nbsp; &lt;lst name="statusMessages"&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Total Requests made to DataSource"&gt;2118645&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Total Rows Fetched"&gt;3177966&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Total Documents Skipped"&gt;0&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Full Dump Started"&gt;2010-10-03 14:28:00&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name=""&gt;Indexing completed. Added/Updated: 1059322 documents. Deleted 0 documents.&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Committed"&gt;2010-10-03 14:55:20&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Optimized"&gt;2010-10-03 14:55:20&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Total Documents Processed"&gt;1059322&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="Time taken "&gt;0:27:20.325&lt;/str&gt;
&nbsp; &lt;/lst&gt;
&nbsp; &lt;str name="WARNING"&gt;This response format is experimental.  It is likely to change in the future.&lt;/str&gt;
&lt;/response&gt;</pre>
<p>Jak widzimy indeksacja zakończyła się sukcesem.</p>
<p>W kolejnym odcinku spróbujemy dodać możliwość importowania przyrostowego.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://solr.pl/2010/10/11/data-import-handler-import-danych-z-baz-sql-cz-1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
