2017-03-08 56 views
0

我使用Solr的6.4草垛2.6.1,pySolr 3.6:Revelants查詢建議用於自動完成使用Solr

我正在尋找類似的建議自動完成一個谷歌。實際使用EdgeNGram的作品不錯,但它返回我的文檔僅標題究竟是不是我想要的:

例如:

typing: 'new y' 
return: 

New york, fabulous city that never sleep 
A trip to new york by night 
... 

這給用戶只有選擇建議列表來選擇特定的文件和搜索將只返回基於建議標題的搜索文檔。

我想要的是像revelants字的建議:

typing: 'new y' 
return: 

new york 
new york by night 
new york city 
trip to new york 

有暗示由返回結果的用戶使用索引查詢,然後將這些查詢作爲建議的文章: https://lucidworks.com/2009/09/08/auto-suggest-from-popular-queries-using-edgengrams/

這意味着解析solr日誌或使用數據庫中一堆保存的用戶查詢中的數據導入(DIH)。

其實這篇文章是很老的(2009年),並自那時以來的Solr已經給我們帶來的建議者(https://cwiki.apache.org/confluence/display/solr/Suggester

無論如何,我不知道是否確實有關於如何使用建議者與revelant查詢,而不是一個很好的教程回到我的文檔標題,而不需要保存用戶的查詢在DB,通過預定程序導入,重新索引等

我search_indexes.py

class ArticleIndex(indexes.SearchIndex, indexes.Indexable): 

    text = indexes.CharField(document=True, use_template=True) 
    created = indexes.DateTimeField(model_attr='created') 
    rating = indexes.IntegerField(model_attr='rating') 
    title = indexes.CharField(model_attr='title', boost=1.125) 
    term = indexes.EdgeNgramField(model_attr='title') 


    def get_model(self): 
      return Article 

我article_text.txt

{{ object.title }} 
{{ object.created }} 
{{ object.rating }} 

我的schema.xml

<field name="term" type="text_general" indexed="true" stored="true" /> 
<field name="weight" type="float" indexed="true" stored="true" /> 

<fieldType name="edge_ngram" class="solr.TextField" positionIncrementGap="1"> 
    <analyzer> 
    <tokenizer class="solr.WhitespaceTokenizerFactory" /> 
    <filter class="solr.LowerCaseFilterFactory" /> 
    <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/> 
    <filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front" /> 
    </analyzer> 
</fieldType> 

<fieldType name="suggestType" class="solr.TextField" positionIncrementGap="100"> 
    <analyzer> 
     <charFilter class="solr.PatternReplaceCharFilterFactory" pattern="[^a-zA-Z0-9]" replacement=" " /> 
     <tokenizer class="solr.WhitespaceTokenizerFactory"/> 
     <filter class="solr.LowerCaseFilterFactory"/> 
    </analyzer> 
</fieldType> 

我solrconfig.xml中

<requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy" > 
    <lst name="defaults"> 
     <str name="suggest">true</str> 
     <str name="suggest.dictionary">infixSuggester</str> 
     <str name="suggest.onlyMorePopular">true</str> 
     <str name="suggest.count">10</str> 
     <str name="suggest.collate">true</str> 
    </lst> 
    <arr name="components"> 
     <str>suggest</str> 
    </arr> 
</requestHandler> 
<searchComponent name="suggest" class="solr.SuggestComponent"> 
    <lst name="suggester"> 
     <str name="name">infixSuggester</str> 
     <str name="lookupImpl">AnalyzingInfixLookupFactory</str> 
     <str name="indexPath">infix_suggestions</str> 
     <str name="highlight">false</str> 
     <str name="dictionaryImpl">DocumentDictionaryFactory</str> 
     <str name="field">term</str> 
     <str name="weightField">weight</str> 
     <str name="suggestAnalyzerFieldType">suggestType</str> 
     <str name="buildOnStartup">false</str> 
     <str name="buildOnCommit">false</str> 
    </lst> 
</searchComponent> 

我用pysolr查詢的Solr作爲草堆沒有實現卻把建議方法:

from pysolr import Solr 

solr = Solr(settings.HAYSTACK_CONNECTIONS['default']['URL'], search_handler='/suggest', use_qt_param=False) 
raw_results = solr.search('', **{'suggest.q': query_string}) 

回答

0

掙扎幾小時後,我終於得到了一些東西。不完美,但足夠好。

根據這篇文章: http://alexbenedetti.blogspot.fr/2015/07/solr-you-complete-me.html

我用FreeTextLookupFactory

我search_indexes.py

class ArticleIndex(indexes.SearchIndex, indexes.Indexable): 

    text = indexes.CharField(document=True, use_template=True) 
    created = indexes.DateTimeField(model_attr='created') 
    rating = indexes.IntegerField(model_attr='rating') 
    title = indexes.CharField(model_attr='title', boost=1.125) 

    def get_model(self): 
      return Article 

我的schema.xml

<field name="django_ct" type="string" indexed="true" stored="true" multiValued="false"/> 
<field name="django_id" type="string" indexed="true" stored="true" multiValued="false"/> 


<field name="text" type="text_en" indexed="true" stored="true" multiValued="false" termVectors="true" /> 
<field name="rating" type="long" indexed="true" stored="true" multiValued="false"/> 
<field name="title" type="text_en" indexed="true" stored="true" multiValued="false"/> 
<field name="created" type="date" indexed="true" stored="true" multiValued="false"/> 

我solrconfig.xml中

<searchComponent name="suggest" class="solr.SuggestComponent"> 
    <lst name="suggester"> 
    <str name="name">suggest</str> 
    <str name="lookupImpl">FreeTextLookupFactory</str> 
    <str name="dictionaryImpl">DocumentDictionaryFactory</str> 
    <str name="field">title</str> 
    <str name="ngrams">3</str> 
    <float name="threshold">0.004</float> 
    <str name="highlight">false</str> 
    <str name="buildOnCommit">false</str> 
    <str name="separator"> </str> 
    <str name="suggestFreeTextAnalyzerFieldType">text_general</str> 
    </lst> 
</searchComponent> 

<requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy" > 
    <lst name="defaults"> 
    <str name="suggest.dictionary">suggest</str> 
    <str name="suggest">true</str> 
    <str name="suggest.count">10</str> 
    </lst> 
    <arr name="components"> 
    <str>suggest</str> 
    </arr> 
</requestHandler> 

,因爲我用的Solr 6.4,這是在默認情況下管理的架構模式(沒有把我在考慮schema.xml中的變化),我不得不在solrconfig.xml中添加切換到手動編輯模式:

<schemaFactory class="ClassicIndexSchemaFactory"/> 

在這裏看到:https://cwiki.apache.org/confluence/display/solr/Schema+Factory+Definition+in+SolrConfig#SchemaFactoryDefinitioninSolrConfig-Switchingfromschema.xmltoManagedSchema

然後重啓Solr的,重建使用草堆指數與rebuild_index

,當然還有與捲曲建建議者: 個捲曲http://127.0.0.1:8983/solr/collection1/suggest?suggest.build=true

最後的結果:

curl http://127.0.0.1:8983/solr/collection1/suggest?suggest.q=new%20y 

我會嘗試到Digg多地進入FreeTextLookupFactory,看看我是否可以使它更準確,但它已經是令人滿意的。 希望得到這個幫助。

PS:時刻關注日誌: http://127.0.0.1:8983/solr/#/~logging 我強烈建議始終在選項卡上打開它。它節省了我的痛苦時間......

+0

這隻會返回單個單詞,而不是您最初想要的短語。您也可以使用帶有帶狀皰疹的FreeTextLookupFactory,如我的答案的第二次編輯中所使用的那樣,這將返回短語而不是單詞。 –

+0

我嘗試了你的改變,仍然返回標題。 – kollo

+0

嗯。您是否將term_suggest的phrase_suggest字段類型(並重新編制了索引)? –

0

爲了您的需要,我建議使用th ËBlendedInfixLookupFactory設置如下:在solrconfig.xml中文件

<field name="title" type="text_general" indexed="true" stored="true" /> 
<field name="term_suggest" type="phrase_suggest" indexed="true" stored="true" multiValued="true"/> 

<copyField source="title" dest="term_suggest"/> 

<fieldType name="phrase_suggest" class="solr.TextField" positionIncrementGap="100"> 
     <analyzer> 
     <tokenizer class="solr.KeywordTokenizerFactory"/> 
     <filter class="solr.LowerCaseFilterFactory"/> 
    </analyzer> 

</fieldType> 
    <fieldType name="text_suggest" class="solr.TextField" positionIncrementGap="100"> 
    <analyzer> 
     <tokenizer class="solr.StandardTokenizerFactory"/> 
     <filter class="solr.LowerCaseFilterFactory"/> 
    </analyzer> 
</fieldType> 

然後:

schema.xml中,創建一個將用於建議者的字段,然後複製到該字段

<searchComponent name="suggest" class="solr.SuggestComponent"> 
    <lst name="suggester"> 
     <str name="name">suggest</str> 
     <str name="lookupImpl">BlendedInfixLookupFactory</str> 
     <str name="blenderType">linear</str> 
     <str name="dictionaryimpl">DocumentDictionaryFactory</str> 
     <str name="field">term_suggest</str> 
     <str name="weightField">weight</str> 
     <str name="suggestAnalyzerFieldType">text_suggest</str> 
     <str name="queryAnalyzerFieldType">phrase_suggest</str> 
     <str name="indexPath">suggest</str> 
     <str name="buildOnStartup">false</str> 
     <str name="buildOnCommit">false</str> 
     <bool name="exactMatchFirst">true</bool> 
    </lst> 
</searchComponent> 

<requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy"> 
    <lst name="defaults"> 
     <str name="echoParams">explicit</str> 
     <str name="wt">json</str> 
     <str name="indent">false</str> 
    <str name="suggest">true</str> 
    <str name="suggest.count">10</str> 
    </lst> 
    <arr name="components"> 
    <str>suggest</str> 
    </arr> 
</requestHandler> 

使用BlendedInfixLookupFactory,您可以在字段中出現的任何位置找到「new y」,從而爲開始時出現的那些賦予更大的權重。將suggestAnalyzerFieldType和關鍵字標記器用於queryAnalyzerFieldType的組合將使它成爲可以使用空格進行搜索(查詢「new y」將被讀作字符串或關鍵字)。

匯合維基鏈接,你貼好,這是最後一次修改在2016年九月

編輯: 我不知道你不想整個標題。您可以嘗試使用帶狀皰疹對於這一點,在上述模式變更的phrase_suggest字段類型此:

<fieldType name="phrase_suggest" class="solr.TextField" positionIncrementGap="100"> 
    <analyzer> 
     <tokenizer class="solr.StandardTokenizerFactory"/> 
     <filter class="solr.LowerCaseFilterFactory"/> 
     <filter class="solr.TrimFilterFactory"/> 
     <filter class="solr.ShingleFilterFactory" 
      minShingleSize="2" 
      maxShingleSize="4" 
      outputUnigrams="true" 
      outputUnigramsIfNoShingles="true"/> 
    </analyzer> 
</fieldType> 

EDIT2: 或者,你可以用標準分詞用鵝卵石過濾器使用phrase_suggest的指數分析儀在查詢分析器關鍵詞分詞:

<fieldType name="phrase_suggest" class="solr.TextField" positionIncrementGap="100"> 
     <analyzer type="index"> 
      <tokenizer class="solr.StandardTokenizerFactory"/> 
     <filter class="solr.LowerCaseFilterFactory"/> 
     <filter class="solr.TrimFilterFactory"/> 
     <filter class="solr.ShingleFilterFactory" 
      minShingleSize="2" 
      maxShingleSize="4" 
      outputUnigrams="true" 
      outputUnigramsIfNoShingles="true"/> 
     </analyzer> 
     <analyzer type="query"> 
      <tokenizer class="solr.KeywordTokenizerFactory"/> 
      <filter class="solr.LowerCaseFilterFactory"/> 
      <filter class="solr.RemoveDuplicatesTokenFilterFactory"/> 
     </analyzer> 
</fieldType> 

那麼對於建議的SearchComponent,你只需要:

<str name="suggestAnalyzerFieldType">phrase_suggest</str> 

(並且沒有queryAnalyzerFieldType)。當然,您需要更改ShingleFilterFactory設置以適應您的需求。

+0

我有2個錯誤 - 第一個線性不存在我用blenderType的position_liner。然後,我不得不添加建議以避免「沒有名爲default的默認配置」錯誤。重新啓動solr,然後curl /suggest?suggest.build=true在我嘗試的每個查詢中都給出零結果。 { 「responseHeader」:{ 「狀態」:0, 「QTIME」:0, 「PARAMS」:{ 「suggest.q」: 「新的y」}}, 「建議」:{ 「建議」 :{ 「new y」:{ 「numFound」:0, 「suggestions」:[]}}}} – kollo

+0

我認爲「linear」或「position_linear」取決於您使用的solr版本。基本問題 - 但是您是否在對schema.xml文件進行更改後重新編制索引?如果您執行簡單查詢(q = *:*&fl = term_suggest),您是否在term_suggest字段中看到數據? (另外,就像你可以直接把你的Django模型放在字段中,而不是使用copyField。) –

+0

我做了一個update_index。但 捲曲http://127.0.0.1:8983/solr/collection1/select/?q=*:*&fl=term_suggest 0 3 *:* term_suggest 如果我ommit領域term_suggest我得到的結果讓一切索引除了term_suggest似乎。 – kollo