<?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>autocomplete &#8211; Solr.pl</title>
	<atom:link href="https://solr.pl/tag/autocomplete-2/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>Fri, 13 Nov 2020 21:34:41 +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>Autocomplete i znaki specjalne</title>
		<link>https://solr.pl/2017/01/29/autocomplete-i-znaki-specjalne/</link>
					<comments>https://solr.pl/2017/01/29/autocomplete-i-znaki-specjalne/#respond</comments>
		
		<dc:creator><![CDATA[Rafał Kuć]]></dc:creator>
		<pubDate>Sun, 29 Jan 2017 21:34:18 +0000</pubDate>
				<category><![CDATA[Solr]]></category>
		<category><![CDATA[autocomplete]]></category>
		<category><![CDATA[solr]]></category>
		<guid isPermaLink="false">http://sematext.solr.pl/?p=710</guid>

					<description><![CDATA[Wiele wody upłynęło w Wiśle odkąd ostatni, prawdziwy post pojawił się na solr.pl. Takie z krwi i kości, opisujący jakiś problem i sugerujący rozwiązanie. Mówią, że lepiej późno, niż wcale, więc nadszedł ten dzień, kiedy znów coś publikujemy 🙂 Wracamy]]></description>
										<content:encoded><![CDATA[<p>Wiele wody upłynęło w Wiśle odkąd ostatni, prawdziwy post pojawił się na <a href="http://solr.pl">solr.pl</a>. Takie z krwi i kości, opisujący jakiś problem i sugerujący rozwiązanie. Mówią, że lepiej późno, niż wcale, więc nadszedł ten dzień, kiedy znów coś publikujemy <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;" /> Wracamy dzisiaj do tematu autocomplete opartej o suggestery, faceting lub n-gramy. Ta sama funkcjonalność, różne podejścia, różne metody realizacji.</p>
<p><span id="more-710"></span></p>
<p>Dzisiaj przyjrzymy się bardziej rozbudowanej funkcjonalonści autocomplete &#8211; takiej, która jest w stanie poradzić sobie ze znakami specjalnymi lub inaczej, znakami niewystępującymi w standardowym zbiorze ASCII.<br />
<!--more--></p>
<h3>Autocomplete ze znakami specjalnymi</h3>
<p>Załóżmy, że nasze dokumenty, na podstawie których chcemy generować wyniki autocomplete, mają tylko dwa pola &#8211; identyfikator i pole <em>name</em>. W polu <em>name</em> możemy napotkać znaki specyficzne dla danego języka, np. takie jak <em>ż</em>, <em>ć</em> lub <em>ę</em> w języku polskim. Co byśmy chcieli to umożliwić generowanie autocomplete dla osób, które nie posiadają klawiatury umożliwiającej wpisanie takich znaków, badź <em>locale</em>, które to umożliwiają w systemie. Zakładamy, iż mamy zaindeksowane następujące dokumenty:
</p>
<pre class="brush:xml">{"id":1, "name":"Pośrednictwo nieruchomości"}
{"id":2, "name":"Posadowienie budynków"}
{"id":3, "name":"Posocznica"}</pre>
<p>Same nazwy nie są znaczące, ważne jest co chcemy osiągnąć. Chcielibyśmy dostać wszystkie trzy dokumenty wpisując <em>pos</em> lub <em>poś</em>. Czy jest to możliwe? Tak i za chwilę zobaczymy, jak to zrobić.</p>
<h3>Przygotowanie konfiguracji kolekcji</h3>
<p>Zacznijmy od pliku konfiguracyjnego <em>schema.xml</em> i definicji pól i ich typów. Kompletnie zignorujemy w tym wypadku wyszukiwanie pełno tekstowe i skoncentrujemy się tylko i wyłącznie na funkcjonalności autocomplete. Dodatkowo zakładamy, iż chcemy zwrócić zawsze całą wartość pola <em>name</em>, jeżeli tylko trafimy w jakikolwiek term w polu <em>name</em>. Definicja naszych pól w pliku <em>schema.xml</em> wygląda następująco:
</p>
<pre class="brush:xml">&lt;field name="id" type="int" indexed="true" stored="true" required="true" multiValued="false" /&gt;
&lt;field name="name" type="string" indexed="false" stored="true" multiValued="false" /&gt;
&lt;field name="name_ac" type="text_ac" indexed="true" stored="false" multiValued="false" /&gt;</pre>
<p>Mamy więc pole <em>id</em>, które jest typu <em>int</em> oraz pole <em>name</em>, które używane jest tylko w celu wyświetlania danych. Pole <em>name_ac</em> to te, z za pomocą którego będziemy generować podpowiedzi autocomplete. Aby ręcznie nie wypełniać pola <em>name_ac</em> skorzystamy z tzw. <em>copyField</em>, który przez analizą skopiuje dane z jednego pola do drugiego (umieszczamy to także w pliku <em>schema.xml</em>):
</p>
<pre class="brush:xml">&lt;copyField source="name" dest="name_ac" /&gt;</pre>
<p>Typ pola <em>name_ac</em> oparty zostanie o mechanizm <em>ngram</em>, czyli przyrostowe generowanie coraz dłuższego przedrostka wartości występującej w tym polu. Do usunięcia znaków pochodzących spoza standardowej tablicy ASCII skorzystamy z filtra <em>solr.ASCIIFoldingFilterFactory</em>. Oczywiście, filtra potrzebujemy zarówno podczas indeksowania, jak i podczas analizy zapytań<em>.</em> Zatem definicja typu <em>text_ac</em> wyglądać będzie następująco:
</p>
<pre class="brush:xml">&lt;fieldType name="text_ac" class="solr.TextField" positionIncrementGap="100"&gt;
  &lt;analyzer type="index"&gt;
    &lt;tokenizer class="solr.KeywordTokenizerFactory"/&gt;
    &lt;filter class="solr.LowerCaseFilterFactory"/&gt;
    &lt;filter class="solr.ASCIIFoldingFilterFactory"/&gt;
    &lt;filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="100" /&gt;
  &lt;/analyzer&gt;
  &lt;analyzer type="query"&gt;
    &lt;tokenizer class="solr.KeywordTokenizerFactory"/&gt;
    &lt;filter class="solr.LowerCaseFilterFactory"/&gt;
    &lt;filter class="solr.ASCIIFoldingFilterFactory"/&gt;
  &lt;/analyzer&gt;
&lt;/fieldType&gt;</pre>
<p>Jak widać jedyną różnicą pomiędzy analizą podczas indeksowania, a tą podczas zapytania jest wykorzystanie filtra <em>solr.EdgeNGramFilterFactory</em> w trakcie indeksowania. Powoduje on przyrostowe generowanie przedrostka i umieszczenie tych wartości w danym polu. Filtra tego nie potrzebujemy podczas zadawania zapytań.</p>
<h3>Czas testowania</h3>
<p>Aby przetestować to co zrobiliśmy uruchomimy Solr w wersji SolrCloud z wbudowanym ZooKeeperem za pomocą następującego polecenia:
</p>
<pre class="brush:xml">$ bin/solr start -c</pre>
<p>Następnie prześlemy konfigurację zawierającą wszystkie nasze zmiany do ZooKeepera używając następującego polecenia:
</p>
<pre class="brush:xml">$ bin/solr zk upconfig -z localhost:9983 -n autocomplete -d /home/config/autocomplete/conf</pre>
<p>Jedyne o czym należy pamiętać, aby powyższe polecenie zadziałało to stworzenie konfiguracji (lub jej pobranie z naszego konta Github &#8211; <a href="http://autocomplete_with_special_chars/conf/">konfiguracja</a>), a następnie umieszczenie jej w odpowiednim katalogu.</p>
<p>Następnie tworzymy kolekcję za pomocą bardzo prostego polecenia:
</p>
<pre class="brush:xml">$ curl 'localhost:8983/solr/admin/collections?action=CREATE&amp;name=autocomplete&amp;numShards=1&amp;replicationFactor=1&amp;collection.configName=autocomplete'</pre>
<p>Po poprawnym wykonaniu polecenia, możemy zaindeksować testowe dokumenty z początku wpisu w następujący sposób:
</p>
<pre class="brush:xml">$ curl "http://localhost:8983/solr/autocomplete/update?commit=true" -H 'Content-type:application/json' -d '[
  {"id":1, "name":"Pośrednictwo nieruchomości"},
  {"id":2, "name":"Posadowienie budynków"},
  {"id":3, "name":"Posocznica"}
]'</pre>
<p>Zadajmy więc dwa zapytania, jedno z literą <em>ś</em>, a drugie z literą <em>s</em> i porównajmy rezultaty. Pierwsze zapytanie wygląda następująco:
</p>
<pre class="brush:xml">http://localhost:8983/solr/autocomplete/select?q.op=AND&amp;defType=edismax&amp;qf=name_ac&amp;fl=id,name&amp;q=pos</pre>
<p>Drugie wygląda natomiast tak:
</p>
<pre class="brush:xml">http://localhost:8983/solr/autocomplete/select?q.op=AND&amp;defType=edismax&amp;qf=name_ac&amp;fl=id,name&amp;q=pos</pre>
<p>W obu przypadkach korzystamy z parsera <em>Extended DisMax</em>, spójnika logicznego <em>AND</em> (parametr <em>q.op</em>) i ustawiamy pole po którym chcemy szukać na <em>name_ac</em> za pomocą parameteru <em>qf</em>. Dodatkowo mówimy Solr, iż chcemy aby zwrócone zostały tylko pola <em>id</em> oraz <em>name</em> za pomocą parametru <em>fl</em>.</p>
<p>W przypadku obu zapytań wyniki są jednakowe i wyglądają następująco:
</p>
<pre class="brush:xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;response&gt;
&lt;lst name="responseHeader"&gt;
  &lt;bool name="zkConnected"&gt;true&lt;/bool&gt;
  &lt;int name="status"&gt;0&lt;/int&gt;
  &lt;int name="QTime"&gt;0&lt;/int&gt;
  &lt;lst name="params"&gt;
    &lt;str name="q"&gt;poś&lt;/str&gt;
    &lt;str name="defType"&gt;edismax&lt;/str&gt;
    &lt;str name="qf"&gt;name_ac&lt;/str&gt;
    &lt;str name="fl"&gt;id,name&lt;/str&gt;
    &lt;str name="q.op"&gt;AND&lt;/str&gt;
  &lt;/lst&gt;
&lt;/lst&gt;
&lt;result name="response" numFound="3" start="0"&gt;
  &lt;doc&gt;
    &lt;int name="id"&gt;1&lt;/int&gt;
    &lt;str name="name"&gt;Pośrednictwo nieruchomości&lt;/str&gt;&lt;/doc&gt;
  &lt;doc&gt;
    &lt;int name="id"&gt;2&lt;/int&gt;
    &lt;str name="name"&gt;Posadowienie budynków&lt;/str&gt;&lt;/doc&gt;
  &lt;doc&gt;
    &lt;int name="id"&gt;3&lt;/int&gt;
    &lt;str name="name"&gt;Posocznica&lt;/str&gt;&lt;/doc&gt;
&lt;/result&gt;
&lt;/response&gt;</pre>
<p>Jak widać opisana metoda 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/2017/01/29/autocomplete-i-znaki-specjalne/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Autocomplete na polach wielowartościowych (faceting)</title>
		<link>https://solr.pl/2013/03/25/autocomplete-na-polach-wielowartosciowych-faceting/</link>
					<comments>https://solr.pl/2013/03/25/autocomplete-na-polach-wielowartosciowych-faceting/#respond</comments>
		
		<dc:creator><![CDATA[Rafał Kuć]]></dc:creator>
		<pubDate>Mon, 25 Mar 2013 11:08:05 +0000</pubDate>
				<category><![CDATA[Solr]]></category>
		<category><![CDATA[autocomplete]]></category>
		<category><![CDATA[faceting]]></category>
		<guid isPermaLink="false">http://sematext.solr.pl/?p=501</guid>

					<description><![CDATA[W poprzednim artykule opisującym możliwe podejście do funkcjonalności autocomplete na polach wielowartościowych skorzystaliśmy z highlightingu, aby wydobyć te informacje, które nas interesowały. Obiecaliśmy także, że wrócimy do tematu i pokażemy, jak osiągnąć podobny efekt z wykorzystaniem facetingu. Zatem, spójrzmy jak]]></description>
										<content:encoded><![CDATA[<p>W <a href="http://solr.pl/2013/02/25/autocomplete-na-polach-wielowartosciowych-highlighting/">poprzednim</a> artykule opisującym możliwe podejście do funkcjonalności autocomplete na polach wielowartościowych skorzystaliśmy z highlightingu, aby wydobyć te informacje, które nas interesowały. Obiecaliśmy także, że wrócimy do tematu i pokażemy, jak osiągnąć podobny efekt z wykorzystaniem facetingu. Zatem, spójrzmy jak wygląda realizacja takiej funkcjonalności.</p>
<p><span id="more-501"></span></p>
<h2>Kilka słów na początek</h2>
<p>Ze względu na to, że jest to niejako kontynuacja poprzedniego wpisu, sugerujemy, aby przeczytać wpis &#8222;<a href="http://solr.pl/2013/02/25/autocomplete-na-polach-wielowartosciowych-highlighting/"><em>Autocomplete na polach wielowartościowych (highlighting)</em></a>&#8222;, aby wszystkie elementy wpisu były jasne. Warto także wspomnieć, iż metoda ta była już pokazywana we wpisie &#8222;<a href="http://solr.pl/2010/10/18/solr-i-autocomplete-cz-1/">Solr i autocomplete (cz. 1)</a>&#8222;, aczkolwiek chcieliśmy przypomnieć ten temat ze względu na częstotliwość pojawiających się pytań.</p>
<h2>Konfiguracja</h2>
<p>Podobnie, jak w poprzednim wpisie zacznijmy od konfiguracji.</p>
<h3>Struktura indeksu</h3>
<p>Struktura naszego indeksu nie różni się od tego co zaprezentowane było w poprzednim wpisie. Jednak, przypomnijmy te informacje &#8211; zakładamy, że chcemy podpowiadać frazy z indeksu z pola wielowartościowego. Pole to nazywa się <em>features</em>, a cała konfiguracja pól w indeksie będzie następująca:
</p>
<pre class="brush:xml">&lt;fields&gt;
 &lt;field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /&gt;
 &lt;field name="features" type="string" indexed="true" stored="true" multiValued="true"/&gt;
 &lt;field name="features_autocomplete" type="text_autocomplete" indexed="true" stored="true" multiValued="true"/&gt;

 &lt;field name="_version_" type="long" indexed="true" stored="true"/&gt;
&lt;/fields&gt;</pre>
<p>Do autocomplete będziemy wykorzystywać pole <em>features_autocomplete</em>.</p>
<h3>Kopiowanie</h3>
<p>Dodatkowo, aby automatycznie zasilać danymi pole <em>features_autocomplete</em> skorzystamy z funkcjonalności copy field, a zatem do pliku <em>schema.xml</em> dodajemy następujący wpis:
</p>
<pre class="brush:xml">&lt;copyField source="features" dest="features_autocomplete"/&gt;</pre>
<h3>Typ text_autocomplete</h3>
<p>Typ <em>text_autocomplete</em> różni się od tego, co widzieliśmy w poprzednim wpisie. Tym razem wygląda on następująco:
</p>
<pre class="brush:xml">&lt;fieldType name="text_autocomplete" class="solr.TextField" positionIncrementGap="100"&gt;
 &lt;analyzer&gt;
  &lt;tokenizer class="solr.KeywordTokenizerFactory"/&gt;
  &lt;filter class="solr.LowerCaseFilterFactory"/&gt;
 &lt;/analyzer&gt;
&lt;/fieldType&gt;</pre>
<p>Ze względu na to, że będziemy korzystać z facetingu korzystamy z <em>solr.KeywordTokenizerFactory</em> oraz sprawiamy, aby wszystkie znaki były małe za pomocą <em>solr.LowerCaseFilterFactory</em>.</p>
<h3>Przykładowe dane</h3>
<p>Nasze dane są identyczne do tych, które wykorzystaliśmy w poprzednim wpisie i wyglądają następująco:
</p>
<pre class="brush:xml">&lt;add&gt;
 &lt;doc&gt;
  &lt;field name="id"&gt;1&lt;/field&gt;
  &lt;field name="features"&gt;Multiple windows&lt;/field&gt;
  &lt;field name="features"&gt;Single door&lt;/field&gt;
 &lt;/doc&gt;
 &lt;doc&gt;
  &lt;field name="id"&gt;2&lt;/field&gt;
  &lt;field name="features"&gt;Single window&lt;/field&gt;
  &lt;field name="features"&gt;Single door&lt;/field&gt;
 &lt;/doc&gt;
 &lt;doc&gt;
  &lt;field name="id"&gt;3&lt;/field&gt;
  &lt;field name="features"&gt;Multiple windows&lt;/field&gt;
  &lt;field name="features"&gt;Multiple doors&lt;/field&gt;
 &lt;/doc&gt;
&lt;/add&gt;</pre>
<h2>Zapytanie z facetingiem</h2>
<p>Zobaczmy zatem, jak wyglądać będzie nasze zapytanie, kiedy wykorzystamy faceting.</p>
<h3>Pełne zapytanie</h3>
<p>W przypadku facetingu nasze zapytanie powinno wyglądać następująco:
</p>
<pre class="brush:xml">q=*:*&amp;rows=0&amp;facet=true&amp;facet.field=features_autocomplete&amp;facet.prefix=sing</pre>
<p>Kilka słów o dodanych parametrach:</p>
<ul>
<li><em>rows=0</em> &#8211; informujemy Solr, że nie jesteśmy zainteresowani wynikami wyszukiwania,</li>
<li><em>facet=true</em> &#8211; informujemy Solr, iż chcemy korzystać z facetingu,</li>
<li><em>facet.field=features_autocomplete</em> &#8211; określamy jakie pole ma zostać wykorzystane do facetingu,</li>
<li><em>facet.prefix=sing</em> &#8211; za pomocą tego parametru przekazujemy interesującą nas frazę.</li>
</ul>
<h3>Wyniki</h3>
<p>Wyniki, które Solr zwraca na powyższe zapytanie, wyglądają następująco:
</p>
<pre class="brush:xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;response&gt;
&lt;lst name="responseHeader"&gt;
&nbsp; &lt;int name="status"&gt;0&lt;/int&gt;
&nbsp; &lt;int name="QTime"&gt;0&lt;/int&gt;
&nbsp; &lt;lst name="params"&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="facet"&gt;true&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="q"&gt;*:*&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="facet.prefix"&gt;sing&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="facet.field"&gt;features_autocomplete&lt;/str&gt;
&nbsp;&nbsp;&nbsp; &lt;str name="rows"&gt;0&lt;/str&gt;
&nbsp; &lt;/lst&gt;
&lt;/lst&gt;
&lt;result name="response" numFound="3" start="0"&gt;
&lt;/result&gt;
&lt;lst name="facet_counts"&gt;
&nbsp; &lt;lst name="facet_queries"/&gt;
&nbsp; &lt;lst name="facet_fields"&gt;
&nbsp;&nbsp;&nbsp; &lt;lst name="features_autocomplete"&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;int name="single door"&gt;2&lt;/int&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;int name="single window"&gt;1&lt;/int&gt;
&nbsp;&nbsp;&nbsp; &lt;/lst&gt;
&nbsp; &lt;/lst&gt;
&nbsp; &lt;lst name="facet_dates"/&gt;
&nbsp; &lt;lst name="facet_ranges"/&gt;
&lt;/lst&gt;
&lt;/response&gt;</pre>
<p>Jak widać, w sekcji odpowiedzialnej za faceting, otrzymaliśmy te frazy, które nas interesowały wraz z ilością dokumentów w jakich się znajdują.</p>
<h3>O czym pamiętać</h3>
<p>Ważną rzeczą jest to, że wartości parametru <em>facet.prefix</em> nie są analizowane, zatem jeżeli zamiast frazy <em>sing</em> przekazalibyśmy frazę <em>Sing</em> Solr nie zwróciłby interesujących nas wyników. Należy o tym pamiętać.</p>
<h2>Podsumowanie</h2>
<p>Powyższy wpis pokazał drugi sposób podejścia do realizacji funkcjonalności autocomplete na polach wielowartościowych. Oczywiście nie wyczerpaliśmy tematu i kiedyś do niego wrócimy, ale na dzisiaj to wszystko. Mamy nadzieję, że komuś się przyda to co znalazł w tych artykułach <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/2013/03/25/autocomplete-na-polach-wielowartosciowych-faceting/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Autocomplete na polach wielowartościowych (highlighting)</title>
		<link>https://solr.pl/2013/02/25/autocomplete-na-polach-wielowartosciowych-highlighting/</link>
					<comments>https://solr.pl/2013/02/25/autocomplete-na-polach-wielowartosciowych-highlighting/#respond</comments>
		
		<dc:creator><![CDATA[Rafał Kuć]]></dc:creator>
		<pubDate>Mon, 25 Feb 2013 11:05:17 +0000</pubDate>
				<category><![CDATA[Solr]]></category>
		<category><![CDATA[autocomplete]]></category>
		<category><![CDATA[highlighting]]></category>
		<category><![CDATA[multivalued]]></category>
		<guid isPermaLink="false">http://sematext.solr.pl/?p=493</guid>

					<description><![CDATA[Jednym z tematów na który natknąłem się ostatnio był problem funkcjonalności autocomplete na polach, które oznaczone są jako multiValued=&#8221;true&#8221; (m.in. pytanie zadano tutaj na Stack Overflow). Przyjrzyjmy się zatem jakie mamy możliwości. Wiele rdzeni kontra jeden rdzeń Jedną z możliwości,]]></description>
										<content:encoded><![CDATA[<p>Jednym z tematów na który natknąłem się ostatnio był problem funkcjonalności autocomplete na polach, które oznaczone są jako <em>multiValued=&#8221;true&#8221;</em> (m.in. pytanie zadano tutaj na <a href="http://stackoverflow.com/questions/14865417/autocomplete-feature-using-solr4-on-multivalued-fields">Stack Overflow</a>). Przyjrzyjmy się zatem jakie mamy możliwości.</p>
<p><span id="more-493"></span></p>
<h2>Wiele rdzeni kontra jeden rdzeń</h2>
<p>Jedną z możliwości, jaką powinniśmy rozważyć na początku, to kwestia tego, czy jesteśmy w stanie stworzyć rdzeń lub kolekcję odpowiedzialną tylko i wyłączenie za autocomplete. Jeżeli tak, to powinniśmy iść tą drogą. Przyczyny tego są proste &#8211; taka kolekcja będzie z reguły mniejsza, niż ta w której indeksowane są nasze dane, ilość termów także ma szansę być mniejsza, a tym samym wykonywanie zapytań powinno być szybsze. Oczywiście, idzie za tym konieczność przygotowania konfiguracji, konieczność indeksacji drugiej kolekcji. Czasami jednak istnieją sytuacje kiedy takie rozwiązanie nie jest możliwe, na przykład ze względu na dodatkowe filtrowanie i takim przypadkiem zajmę się w tym wpisie.</p>
<p>Załóżmy dodatkowo że chcemy podpowiadać pełne frazy.</p>
<h2>Konfiguracja</h2>
<p>Zacznijmy zatem od konfiguracji.</p>
<h3>Struktura indeksu</h3>
<p>Załóżmy, że chcemy podpowiadać frazy z indeksu, oczywiście z pola wielowartościowego. Niech pole to nazywa się <em>features</em>, a cała konfiguracja pól w indeksie będzie następująca:
</p>
<pre class="brush:xml">&lt;fields&gt;
 &lt;field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /&gt;
 &lt;field name="features" type="string" indexed="true" stored="true" multiValued="true"/&gt;
 &lt;field name="features_autocomplete" type="text_autocomplete" indexed="true" stored="true" multiValued="true"/&gt;

 &lt;field name="_version_" type="long" indexed="true" stored="true"/&gt;
&lt;/fields&gt;</pre>
<p>Jak widać do autocomplete będziemy wykorzystywać pole <em>features_autocomplete</em>. Pole <em>_version_</em> wymagane jest przez niektóre funkcjonalności Solr 4.0 i nowszych i dlatego jest obecne w naszym indeksie.</p>
<h3>Kopiowanie</h3>
<p>Dodatkowo, aby automatycznie zasilać danymi pole <em>features_autocomplete</em> skorzystamy z funkcjonalności copy field, a zatem do pliku <em>schema.xml</em> dodajemy następujący wpis:
</p>
<pre class="brush:xml">&lt;copyField source="features" dest="features_autocomplete"/&gt;</pre>
<h3>Typ text_autocomplete</h3>
<p>Przyjrzyjmy się teraz jak wygląda nasz typ <em>text_autocomplete</em>:
</p>
<pre class="brush:xml">&lt;fieldType name="text_autocomplete"&nbsp;class="solr.TextField" positionIncrementGap="100"&gt;
 &lt;analyzer type="index"&gt;
  &lt;tokenizer class="solr.KeywordTokenizerFactory"/&gt;
  &lt;filter class="solr.LowerCaseFilterFactory"/&gt;
  &lt;filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="50" /&gt;
 &lt;/analyzer&gt;
 &lt;analyzer type="query"&gt;
  &lt;tokenizer class="solr.KeywordTokenizerFactory" /&gt;
  &lt;filter class="solr.LowerCaseFilterFactory"/&gt;
 &lt;/analyzer&gt;
&lt;/fieldType&gt;</pre>
<p>Jak widać w trakcie indeksowania będziemy tworzyć kolejne rozwinięcia naszej frazy zawartej w polu <em>features_autocomplete </em>za pomocą filtra <em>solr.EdgeNGramFilterFactory</em>. Minimalna długość powstałego tokoena może mieć długość 2, a najdłuższy może mieć długość 50 znaków.</p>
<p>Na etapie zapytania sprowadzamy frazę tylko do wspólnego mianownika za pomocą <em>solr.LowerCaseFilterFactory</em> i filtrów tworzonych przez tą fabrykę.</p>
<h3>Przykładowe dane</h3>
<p>Nasze dane wyglądają następująco:
</p>
<pre class="brush:xml">&lt;add&gt;
 &lt;doc&gt;
  &lt;field name="id"&gt;1&lt;/field&gt;
  &lt;field name="features"&gt;Multiple windows&lt;/field&gt;
  &lt;field name="features"&gt;Single door&lt;/field&gt;
 &lt;/doc&gt;
 &lt;doc&gt;
  &lt;field name="id"&gt;2&lt;/field&gt;
  &lt;field name="features"&gt;Single window&lt;/field&gt;
  &lt;field name="features"&gt;Single door&lt;/field&gt;
 &lt;/doc&gt;
 &lt;doc&gt;
  &lt;field name="id"&gt;3&lt;/field&gt;
  &lt;field name="features"&gt;Multiple windows&lt;/field&gt;
  &lt;field name="features"&gt;Multiple doors&lt;/field&gt;
 &lt;/doc&gt;
&lt;/add&gt;</pre>
<h2>Podstawowe zapytania</h2>
<p>Spójrzmy zatem na zapytania.</p>
<h3>Na początek</h3>
<p>Zacznijmy od prostego zapytania, które w przypadku kiedy mielibyśmy pole przechowujące pojedyncze wartości zwróciłoby nam dane, które nas interesują. Zapytanie takie mogłoby wyglądać następująco:
</p>
<pre class="brush:xml">q=features_autocomplete:sing&amp;fl=features_autocomplete</pre>
<h3>Wyniki</h3>
<p>Wyniki, jakie otrzymujemy z takiego zapytania to:
</p>
<pre class="brush:xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;response&gt;
 &lt;lst name="responseHeader"&gt;
  &lt;int name="status"&gt;0&lt;/int&gt;
  &lt;int name="QTime"&gt;3&lt;/int&gt;
  &lt;lst name="params"&gt;
   &lt;str name="fl"&gt;features_autocomplete&lt;/str&gt;
   &lt;str name="q"&gt;features_autocomplete:sing&lt;/str&gt;
  &lt;/lst&gt;
 &lt;/lst&gt;
 &lt;result name="response" numFound="2" start="0"&gt;
 &lt;doc&gt;
  &lt;arr name="features_autocomplete"&gt;
   &lt;str&gt;Single window&lt;/str&gt;
   &lt;str&gt;Single door&lt;/str&gt;
  &lt;/arr&gt;
 &lt;/doc&gt;
 &lt;doc&gt;
  &lt;arr name="features_autocomplete"&gt;
   &lt;str&gt;Multiple windows&lt;/str&gt;
   &lt;str&gt;Single door&lt;/str&gt;
  &lt;/arr&gt;
 &lt;/doc&gt;
 &lt;/result&gt;
&lt;/response&gt;</pre>
<h3>Krótki komentarz</h3>
<p>Jak widać wyniki, jakie otrzymaliśmy nie satysfakcjonują nas, ze względu na to, że oprócz wartości, w której Solr znalazł trafienie, dostajemy także resztę danych w polu wielowartościowym. Zmodyfikujmy zatem nasze zapytanie.</p>
<h2>Zapytanie z highlightingiem</h2>
<p>Jak widać musimy zmienić nasze zapytanie, aby otrzymać to czego potrzebujemy. Wykorzystamy do tego highlighting.</p>
<h3>Zmienione zapytanie</h3>
<p>Zmieńmy zatem nasze zapytanie dodając następujący fragment:
</p>
<pre class="brush:xml">hl=true&amp;hl.fl=features_autocomplete&amp;hl.simple.pre=&amp;hl.simple.post=</pre>
<p>Zatem całe zapytanie wygląda następująco:
</p>
<pre class="brush:xml">q=features_autocomplete:sing&amp;fl=features_autocomplete&amp;hl=true&amp;hl.fl=features_autocomplete&amp;hl.simple.pre=&amp;hl.simple.post=</pre>
<p>Kilka słów o dodanych parametrach:</p>
<ul>
<li><em>hl=true</em> &#8211; informujemy Solr, iż chcemy korzystać z highlightingu,</li>
<li><em>hl.fl=features_autocomplete</em> &#8211; określamy jakie pole ma zostać wykorzystane do highlightingu,</li>
<li><em>hl.simple.pre=</em> &#8211; stwierdzamy, iż nie chcemy widzieć gdzie zaczyna się podświetlony fragment,</li>
<li><em>hl.simple.post=</em> &#8211; stwierdzamy, iż nie chcemy widzieć gdzie kończy się podświetlony fragment.</li>
</ul>
<h3>Wyniki</h3>
<p>Wyniki, które Solr zwraca na powyższe zapytanie, wyglądają następująco:
</p>
<pre class="brush:xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;response&gt;
 &lt;lst name="responseHeader"&gt;
  &lt;int name="status"&gt;0&lt;/int&gt;
  &lt;int name="QTime"&gt;4&lt;/int&gt;
  &lt;lst name="params"&gt;
   &lt;str name="fl"&gt;features_autocomplete&lt;/str&gt;
   &lt;str name="q"&gt;features_autocomplete:sing&lt;/str&gt;
   &lt;str name="hl.simple.pre"/&gt;
   &lt;str name="hl.simple.post"/&gt;
   &lt;str name="hl.fl"&gt;features_autocomplete&lt;/str&gt;
   &lt;str name="hl"&gt;true&lt;/str&gt;
  &lt;/lst&gt;
 &lt;/lst&gt;
 &lt;result name="response" numFound="2" start="0"&gt;
 &lt;doc&gt;
  &lt;arr name="features_autocomplete"&gt;
   &lt;str&gt;Single window&lt;/str&gt;
   &lt;str&gt;Single door&lt;/str&gt;
  &lt;/arr&gt;
 &lt;/doc&gt;
 &lt;doc&gt;
  &lt;arr name="features_autocomplete"&gt;
   &lt;str&gt;Multiple windows&lt;/str&gt;
   &lt;str&gt;Single door&lt;/str&gt;
  &lt;/arr&gt;
 &lt;/doc&gt;
 &lt;/result&gt;
 &lt;lst name="highlighting"&gt;
  &lt;lst name="2"&gt;
   &lt;arr name="features_autocomplete"&gt;
    &lt;str&gt;Single window&lt;/str&gt;
   &lt;/arr&gt;
  &lt;/lst&gt;
  &lt;lst name="1"&gt;
   &lt;arr name="features_autocomplete"&gt;
    &lt;str&gt;Single door&lt;/str&gt;
   &lt;/arr&gt;
  &lt;/lst&gt;
 &lt;/lst&gt;
&lt;/response&gt;</pre>
<p>Jak widać, w sekcji odpowiedzialnej za highlighting, otrzymaliśmy te frazy, które nas interesowały.</p>
<h2>Podsumowanie</h2>
<p>Należy pamiętać, iż przedstawiony sposób nie jest jedynym sposobem rozwiązania przedstawionego problemu. W kolejnym wpisie przedstawimy, jak ten sam problem można rozwiązać przy pomocy facetingu, jeżeli tylko jesteśmy w stanie zaakceptować pewne niedogodności, ale o tym w następnym wpisie dotyczącym funkcjonalności autocomplete.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://solr.pl/2013/02/25/autocomplete-na-polach-wielowartosciowych-highlighting/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Autcomplete, cz. 4 (Ngram i faceting)</title>
		<link>https://solr.pl/2012/05/28/autcomplete-cz-4-ngram-i-faceting/</link>
					<comments>https://solr.pl/2012/05/28/autcomplete-cz-4-ngram-i-faceting/#respond</comments>
		
		<dc:creator><![CDATA[Marek Rogoziński]]></dc:creator>
		<pubDate>Mon, 28 May 2012 21:31:05 +0000</pubDate>
				<category><![CDATA[Solr]]></category>
		<category><![CDATA[autocomplete]]></category>
		<guid isPermaLink="false">http://sematext.solr.pl/?p=418</guid>

					<description><![CDATA[W poprzednich częściach przedstawiliśmy dwie metody tworzenia podpowiadania zapytań. Następnie jedną z nich rozbudowaliśmy o możliwość dodatkowego definiowania zwracanych informacji. W tym artykule wrócimy ponownie wykorzystamy faceting oraz ngram. Wymagania Przy tworzeniu listy podpowiedzi przyjęliśmy następujące założenia: Podpowiadana jest cała]]></description>
										<content:encoded><![CDATA[<p>W poprzednich częściach przedstawiliśmy dwie metody tworzenia podpowiadania zapytań. Następnie jedną z nich rozbudowaliśmy o możliwość dodatkowego definiowania zwracanych informacji. W tym artykule wrócimy ponownie wykorzystamy faceting oraz ngram.
</p>
<h2 align="LEFT">Wymagania</h2>
<p align="LEFT">Przy tworzeniu listy podpowiedzi przyjęliśmy następujące założenia:</p>
<p><span id="more-418"></span></p>
<ol>
<li>Podpowiadana jest cała fraza a nie tylko pojedyncze słowo</li>
<li>Podpowiadana fraza może wystąpić w indeksie wielokrotnie</li>
<li>w wyniku chcemy znać liczbę wystąpień</li>
<li>Częściej występujące frazy są podpowiadane w pierwszej kolejności</li>
<li>Kolejność podawanych przez użytkownika słów nie musi odpowiadać kolejności występowania słów w podpowiadanej frazie</li>
</ol>
<h2>Rozwiązanie</h2>
<p style="text-align: justify;" align="LEFT">Podany w pierwszej części sposób odpada ze względu na pierwsze założenie. Co prawda wyszukiwanie słów we frazie da się prosto osiągnąć zmieniając sposób analizy, jednak zwracane są pojedyncze słowa a nie cała fraza.</p>
<p style="text-align: justify;" align="LEFT">Rozwiązanie to zmodyfikowana wersja sposobu z facetingiem. Zamiast stosować wyszukiwanie wszystkich elementów i zawężanie wyników facetingu poprzez facet.prefix, możemy od razu wyszukać tylko te elementy, które mają fragment słowa wpisanego przez użytkownika. Ponieważ nie chcemy stosować zapytania prefiksowego ( „słowo*” ) ze względów wydajnościowych, na pomoc wezwiemy ngramy. Oznacza to zapisanie w indeksie wszystkich przedrostków słowa. Oczywistą wadą jest rozrost indeksu, ale w naszym przypadku jesteśmy w stanie z tym żyć <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 style="text-align: justify;" align="LEFT">Schema.xml</h2>
<p style="text-align: justify;" align="LEFT">Definiujemy więc dodatkowy typ:</p>
<pre class="brush:xml">  &lt;fieldType name="text_autocomplete" class="solr.TextField" positionIncrementGap="100"&gt;
    &lt;analyzer type="index"&gt;
      &lt;tokenizer class="solr.WhitespaceTokenizerFactory"/&gt;
      &lt;filter class="solr.LowerCaseFilterFactory"/&gt;
      &lt;filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="25" /&gt;
    &lt;/analyzer&gt;
    &lt;analyzer type="query"&gt;
      &lt;tokenizer class="solr.WhitespaceTokenizerFactory"/&gt;
      &lt;filter class="solr.LowerCaseFilterFactory"/&gt;
    &lt;/analyzer&gt;
  &lt;/fieldType&gt;</pre>
<p align="LEFT">Oraz pola: to, którego wartość będziemy wyświetlać oraz te, służące do wyszukiwania:</p>
<pre class="brush:xml">&lt;field name="tag_autocomplete" type="text_autocomplete" indexed="true" stored="true" omitNorms="true" omitTermFreqAndPositions="true"/&gt;
&lt;field name="tag" type="string" indexed="true" stored="true" /&gt;</pre>
<p align="LEFT">Zostaje jeszcze odpowiedni copyField:</p>
<pre class="brush:xml">&lt;copyField source="tag" dest="tag_autocomplete"/&gt;</pre>
<h2>&nbsp;Zapytanie</h2>
<p align="LEFT">Po przeindeksowaniu możemy przystąpić do tworzenia zapytania:</p>
<ol>
<li>Zawężamy listę wyników do tych, które w polu tag_autocomplete mają poszukiwany fragment słowa: q=tag_autocomplete:(FRAZA)</li>
<li>W przypadku wielu podanych przez użytkownika fragmentów słów istotne jest, by były one wyszukiwane wszystkie: q.op=AND</li>
<li>Tak naprawdę wyniki nie są istotne, dane odczytamy z facetingu, więc informujemy solr, że nie potrzebujemy listy wyników: rows=0</li>
<li>Potrzebujemy natomiast faceting: facet=true</li>
<li>W dodatku to faceting po polu w którym przechowujemy oryginalną zawartość pola podpowiedzi: facet.field=tag</li>
<li>Nie interesują nas tagi, które nie zostały znalezione: facet.mincount=1</li>
<li>Interesuje nas 5 wyników: facet.limit=5</li>
</ol>
<p align="LEFT">Ostateczne zapytanie:</p>
<pre>?q=tag_autocomplete:(FRAZA)&amp;q.op=AND&amp;rows=0&amp;facet=true&amp;facet.field=tag&amp;facet.mincount=1&amp;facet.limit=5</pre>
<p align="LEFT">Jeśli parametry, które są stałe umieścimy w handlerze, jako wartości domyślne, to zapytanie sprowadza się do:</p>
<pre>?q=tag_autocomplete:(FRAZA)</pre>
<h2>Słowo na koniec</h2>
<p align="LEFT">Podstawową zaletą tego rozwiązania w stosunku do rozwiązania opartego o faceting i facet.prefix jest możliwość używania innego pola do zwracania podpowiedzi. Dzięki temu przy podpowiadaniu pojedynczych słów możemy w wyniku wyświetlić całą zawartość pola „tag”.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://solr.pl/2012/05/28/autcomplete-cz-4-ngram-i-faceting/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Solr i autocomplete (cz. 3)</title>
		<link>https://solr.pl/2010/11/29/solr-i-autocomplete-cz-3/</link>
					<comments>https://solr.pl/2010/11/29/solr-i-autocomplete-cz-3/#respond</comments>
		
		<dc:creator><![CDATA[Rafał Kuć]]></dc:creator>
		<pubDate>Mon, 29 Nov 2010 22:32:33 +0000</pubDate>
				<category><![CDATA[Solr]]></category>
		<category><![CDATA[autocomplete]]></category>
		<category><![CDATA[component]]></category>
		<category><![CDATA[solr]]></category>
		<category><![CDATA[suggest component]]></category>
		<category><![CDATA[suggester]]></category>
		<guid isPermaLink="false">http://sematext.solr.pl/?p=144</guid>

					<description><![CDATA[W poprzednich częściach (cz. 1, cz. 2) cyklu dowiedzieliśmy w jaki sposób można wykorzystać Solr, aby uzyskać funkcjonalność autocomplete. W dzisiejszym wpisie pokażę w jaki sposób dodać do komponentu Suggester słownik, a tym samym mieć wpływ na generowane podpowiedzi. Konfiguracja]]></description>
										<content:encoded><![CDATA[<p>W poprzednich częściach (<a href="http://solr.pl/2010/10/18/solr-i-autocomplete-cz-1/">cz. 1</a>, <a href="http://solr.pl/2010/11/15/solr-i-autocomplete-cz-2/">cz. 2</a>) cyklu dowiedzieliśmy w jaki sposób można wykorzystać Solr, aby uzyskać funkcjonalność autocomplete. W dzisiejszym wpisie pokażę w jaki sposób dodać do komponentu Suggester słownik, a tym samym mieć wpływ na generowane podpowiedzi.</p>
<p><span id="more-144"></span></p>
<p><img fetchpriority="high" decoding="async" class="size-full wp-image-483" title="Google Autocomplete" src="http://solr.pl/wp-content/uploads/2010/10/google_autocomplete2.png" alt="" width="641" height="159"></p>
<h3>Konfiguracja komponentu</h3>
<p>Do konfiguracji komponentu przedstawionej w poprzedniej części dodajmy następujący parametr:
</p>
<pre class="brush:xml">&lt;str name="sourceLocation"&gt;dict.txt&lt;/str&gt;</pre>
<p>Zatem nasza konfiguracja powinna wyglądać następująco:
</p>
<pre class="brush:xml">&lt;searchComponent name="suggest" class="solr.SpellCheckComponent"&gt;
 &lt;lst name="spellchecker"&gt;
&nbsp; &lt;str name="name"&gt;suggest&lt;/str&gt;
&nbsp; &lt;str name="classname"&gt;org.apache.solr.spelling.suggest.Suggester&lt;/str&gt;
  &lt;str name="lookupImpl"&gt;org.apache.solr.spelling.suggest.tst.TSTLookup&lt;/str&gt;
  &lt;str name="field"&gt;name_autocomplete&lt;/str&gt;
  &lt;str name="sourceLocation"&gt;dict.txt&lt;/str&gt;
 &lt;/lst&gt;
&lt;/searchComponent&gt;</pre>
<p>Poinformowaliśmy komponent, że ma korzystać ze słownika o nazwie <em>dict.txt</em>, który znajduje się w katalogu z plikami konfiguracyjnymi Solr.</p>
<h3>Konfiguracja handlera</h3>
<p>Do konfiguracji handlera także dodamy jeden parametr, będzie on następujący:
</p>
<pre class="brush:xml">&lt;str name="spellcheck.onlyMorePopular"&gt;true&lt;/str&gt;</pre>
<p>Zatem konfiguracja powinna wyglądać następująco:
</p>
<pre class="brush:xml">&lt;requestHandler name="/suggest" class="org.apache.solr.handler.component.SearchComponent"&gt;
 &lt;lst name="defaults"&gt;
&nbsp; &lt;str name="spellcheck"&gt;true&lt;/str&gt;
&nbsp; &lt;str name="spellcheck.dictionary"&gt;suggest&lt;/str&gt;
&nbsp; &lt;str name="spellcheck.count"&gt;10&lt;/str&gt;
  &lt;str name="spellcheck.onlyMorePopular"&gt;true&lt;/str&gt;
 &lt;/lst&gt;
 &lt;arr name="components"&gt;
&nbsp; &lt;str&gt;suggest&lt;/str&gt;
 &lt;/arr&gt;
&lt;/requestHandler&gt;</pre>
<p>Parametr ten mówi, aby komponent zwrócił tylko takie podpowiedzi, dla których ilość wyników wyszukiwania będzie większa od ilości wyników wyszukiwania dla aktualnego zapytania.</p>
<h3>Słownik</h3>
<p>Wcześniej powiedzieliśmy Solr, aby korzystał ze słownika, ale jak ma wyglądać przykładowy słownik. Do celów artykułu zdefiniowałem następujący słownik:
</p>
<pre class="brush:plain"># przykladowy slownik
Dysk twardy hitachi
Dysk twardy wd    2.0
Dysk twardy jjdd    3.0
</pre>
<p>Jak wygląda konstrukcja słownika ? Każda z fraz (bądź pojedynczy wyrazów) znajduje się w oddzielnej linii. Każda linia zakończona jest wagą danej frazy (pomiędzy wagą a frazą występuje znak tabulacji) wykorzystywanej wraz z parametrem <em>spellcheck.onlyMorePopular=true</em> (im wyższa waga, tym wyżej znajdzie się podpowiedź). W przypadku pominięcia wagi Solr sam dodaje wartość domyślną wynoszącą 1. Słownik powinien być zapisany w kodowaniu UTF-8. Linie rozpoczynające się od znaku # są pomijane.</p>
<h3>Dane</h3>
<p>W tym wypadku nie potrzebujemy danych &#8211; komponent korzysta jedynie ze słownika.</p>
<h3>Sprawdźmy jak to działa</h3>
<p>W celu sprawdzenia jak działa nasz mechanizm zadajemy do Solr następujące zapytanie, oczywiście wcześniej przebudowując indeks mechanizmu:</p>
<p><code>/suggest?q=Dys</code></p>
<p>W odpowiedzi dostajemy następujące wyniki:
</p>
<pre class="brush:xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;response&gt;
&lt;lst name="responseHeader"&gt;
  &lt;int name="status"&gt;0&lt;/int&gt;
  &lt;int name="QTime"&gt;0&lt;/int&gt;
&lt;/lst&gt;
&lt;lst name="spellcheck"&gt;
  &lt;lst name="suggestions"&gt;
    &lt;lst name="Dys"&gt;
      &lt;int name="numFound"&gt;3&lt;/int&gt;
      &lt;int name="startOffset"&gt;0&lt;/int&gt;
      &lt;int name="endOffset"&gt;3&lt;/int&gt;
      &lt;arr name="suggestion"&gt;
        &lt;str&gt;Dysk twardy jjdd&lt;/str&gt;
        &lt;str&gt;Dysk twardy hitachi&lt;/str&gt;
        &lt;str&gt;Dysk twardy wd&lt;/str&gt;
     &lt;/arr&gt;
    &lt;/lst&gt;
  &lt;/lst&gt;
&lt;/lst&gt;
&lt;/response&gt;
</pre>
<h3>Kilka słów na koniec</h3>
<p>Jak widać podpowiedzi zostały posortowane według wysokości wag, czyli zgodnie z oczekiwaniami. Warto zauważyć także, że zapytanie zostało zadane dużą literą, co również ma dość duże znaczenie &#8211; zadanie zapytania małą literą spowoduje wygenerowanie zerowej listy podpowiedzi.</p>
<p>Co można powiedzieć o metodzie &#8211; jeżeli mamy bardzo dobre słowniki z wygenerowanymi wagami np. na podstawie zachowań klientów, jest to metoda generowania podpowiedzi, która zdobędzie sympatię klientów. Nie polecam jej jednak w przypadku pierwszych kroków z podpowiedziami i nieposiadania słowników &#8211; wtedy podpowiedzi mogą, choć oczywiście nie muszą, być słabej jakości.</p>
<h3>Co dalej</h3>
<p>Ilość zajęć nie pozwoliła mi niestety na przeprowadzenie testów wydajnościowych poszczególnych metod, dlatego też w następnej części postaram się przedstawić, jak zachowują się poszczególne metody w zależności od struktury i wielkości indeksu.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://solr.pl/2010/11/29/solr-i-autocomplete-cz-3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
