1. 程式人生 > >schema.xml的配置

schema.xml的配置

sortable 覆蓋面 提高 怎麽辦 加載數據 trie 創建 auto pic

schema.xml做什麽?

SOLR加載數據,創建索引和數據時,核心數據結構的配置文件是schema.xml,該配置文件主要用於配置數據源,字段類型定義,搜索類型定義等。schema.xml的配置直接影響搜索結果的準確性與效率。

<types></types>節點

types節點主要用於搜索類型的定義,這裏給出常用類型的定義。

<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
<fieldType name="boolean" class="solr.BoolField
" sortMissingLast="true"/> <fieldtype name="binary" class="solr.BinaryField"/> <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/> <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/> <fieldType name="
long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/> <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/> <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/> <fieldType name="tfloat
" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/> <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/> <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/> <fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/> <fieldType name="tdate" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="0"/> <fieldType name="pint" class="solr.IntField"/> <fieldType name="plong" class="solr.LongField"/> <fieldType name="pfloat" class="solr.FloatField"/> <fieldType name="pdouble" class="solr.DoubleField"/> <fieldType name="pdate" class="solr.DateField" sortMissingLast="true"/> <fieldType name="sint" class="solr.SortableIntField" sortMissingLast="true" omitNorms="true"/> <fieldType name="slong" class="solr.SortableLongField" sortMissingLast="true" omitNorms="true"/> <fieldType name="sfloat" class="solr.SortableFloatField" sortMissingLast="true" omitNorms="true"/> <fieldType name="sdouble" class="solr.SortableDoubleField" sortMissingLast="true" omitNorms="true"/> <fieldType name="random" class="solr.RandomSortField" indexed="true" />

這裏給出的類型有,字符串,bool,int,date等等,基本java常用的都有。下面解釋一下各個參數的意思。

name:定義搜索字段名

class:這個搜索字段實際使用的類與方法。在org.appache.solr.analysis包下,包括了常用的類型。

其他可選的屬性:

sortMissingLast,sortMissingFirst兩個屬性是用在可以內在使用String排序的類型上,默認false,適用於字段類型:string,boolean,sint,slong,sfloat,sdouble,pdate。

sortMissingLast="true",沒有該field的數據排在有該field的數據之後,而不管請求時的排序規則,在Java中對應的意思就是,該字段為NULL,排在後面。

sortMissingFirst="true",排序規則與sortMissingLast相反。

positionIncrementGap:可選屬性,定義在同一個文檔中此類型數據的空白間隔,避免短語匹配錯誤。

在配置中,string類型的class是solr.StrField,而這個字段是不會被分析存儲的,也就是說不會被分詞。

而對於文章或者長文本來說,我們必須對其進行分詞才能保證搜索某些字段時能夠給出正確的結果。這時我們就可以用到另外一個class,solr.TextField。它允許用戶通過分析器來定制索引和查詢,分析器包括一個分詞器(tokenizer)和多個過濾器(filter) 。

下面就來看一下中文分詞吧,這裏用的分詞是IK Analyzer 2012。

中文分詞

<!-- IKAnalyzer2012 -->
<fieldType name="text_ika" class="solr.TextField">
    <analyzer type="index" positionIncrementGap="100" autoGeneratePhraseQueries="true">
        <tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory" isMaxWordLength="false"/>
        <!-- <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" /> -->
        <!-- <filter class="solr.LowerCaseFilterFactory"/> -->
    </analyzer>
    <analyzer type="query">
        <tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory" isMaxWordLength="true" />
        <!-- <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" /> -->
        <!-- <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/> -->
        <!-- <filter class="solr.LowerCaseFilterFactory"/> -->
    </analyzer>
</fieldType>

分詞用的依舊是fieldType,為的是在下面的field中能夠用到。

有兩個analyzer,一個是index,一個是query,index是針對於所有,query是針對於搜索。

可以看到我註掉了兩個filter,為什麽呢。

先說簡單的吧,一個是query中的同義詞Filter,solr.SynonymFilterFactory,註掉他是因為當前沒有一個龐大的詞庫能夠支撐中文如此復雜的同義詞量。

另外一個是忽略大小寫的Filter,這個Filter可以根據自己的需要進行添加或刪除,在我們的系統中,主要處理中文,這個用處也不大。

還有一個註掉的Filter是停詞Filter,這個用處挺大的,為什麽註掉呢?因為我感覺他在這裏不太合適。

解釋一下:停詞組件在中文分詞中很重要,IK也提供了相對應的配置方法,不僅僅可以處理停詞,而且還可以自定義詞庫。所以,我建議將停詞在IK中配置而不是在schema.xml中。

兩種方法都說一下:

第一種:在schema.xml中配置,不要註釋stopword組件,並將停詞文件拷貝至solrHome/core/conf目錄下(註意文件的編碼方式,至少保證文本文件是UTF-8格式,更加嚴格的,保證文本文件是無BOM格式的UTF-8編碼)。

第二種:在IK配置文件中配置,請下載一個IK分詞組件,裏面會有一個IKAnalyzer.cfg.xml的配置文件,拷貝到solr項目的源代碼根目錄下,並將stopword.dic也拷貝到根目錄下,如下圖所示:

技術分享

記得要導入IK的Jar包,這樣,在你的文件中就可以使用IK提供的中文分詞了。

IK也可以自定義詞庫,這個可以看一下IK的文檔,很簡單,將你的自定義詞庫的文件拷貝至根目錄,並在IK配置文件中配置即可。

<fields></fields>節點

filed字段用於定義數據源字段所使用的搜索類型與相關設置。

<field name="id" type="long" indexed="true" stored="true" multiValued="false" required="true" />
<field name="name" type="text_ika" indexed="true" stored="true" multiValued="false" />
<field name="address" type="text_ika" indexed="true" stored="true" multiValued="false" />
<field name="description" type="text_ika" indexed="true" stored="true" multiValued="false" />
<field name="saturdayMerchant" type="boolean" indexed="true" stored="true" multiValued="false" />
<field name="huiMerchant" type="boolean" indexed="true" stored="true" multiValued="false" />
<field name="bankMerchant" type="boolean" indexed="true" stored="true" multiValued="false" />
<field name="rebate" type="int" indexed="true" stored="true" multiValued="false" />
<field name="valid" type="boolean" indexed="true" stored="true" multiValued="false" />
<field name="createTime" type="date" indexed="true" stored="true" multiValued="false" />
<field name="priority" type="int" indexed="true" stored="true" multiValued="false" />
<field name="telephone" type="string" indexed="true" stored="true" multiValued="false" />
<field name="city" type="text_ika" indexed="true" stored="true" multiValued="false" />
<field name="district_id" type="long" indexed="true" stored="true" multiValued="false" />
<field name="district_name" type="text_ika" indexed="true" stored="true" multiValued="false" />
<field name="merchantCategory_id" type="long" indexed="true" stored="true" multiValued="false" />
<field name="merchantCategory_name" type="text_ika" indexed="true" stored="true" multiValued="false" />
<field name="bank_id" type="long" indexed="true" stored="true" multiValued="true" />
<field name="bank_name" type="text_ika" indexed="true" stored="true" multiValued="true" />

<field name="all" type="text_ika" indexed="true" stored="false" multiValued="true" />

name:數據源字段名,搜索使用到。

type:搜索類型名例如中文ika搜索名text_ika,對應於fieldType中的name。不需要分詞的字符串類型,string即可,如果需要分詞,用上面配置好的分詞type。

indexed:是否被索引,只有設置為true的字段才能進行搜索排序分片(earchable, sortable, facetable)。

stored:是否存儲內容,如果不需要存儲字段值,盡量設置為false以提高效率。

multiValued:是否為多值類型,SOLR允許配置多個數據源字段存儲到一個搜索字段中。多個值必須為true,否則有可能拋出異常。

copyField節點

如果我們的搜索需要搜索多個字段該怎麽辦呢?這時候,我們就可以使用copyField。代碼如下:

<copyField source="name" dest="all" />
<copyField source="address" dest="all" />
<copyField source="description" dest="all" />
<copyField source="city" dest="all" />
<copyField source="district_name" dest="all" />
<copyField source="merchantCategory_name" dest="all" />
<copyField source="bank_name" dest="all" />

我們將所有的中文分詞字段全部拷貝至all中,當我們進行全文檢索是,只用搜索all字段就OK了。

註意,這裏的目標字段必須支持多值,最好不要存儲,因為他只是做搜索。indexed為true,stored為false。

copyField節點和field節點都在fields節點之內。

問題又來了,如果需要根據不同的重要性進行區分,例如name的重要性比address大,該怎麽辦呢,後面再說這個問題。

uniqueKey節點

solr必須設置一個唯一字段,常設置為id,此唯一一段有uniqueKey節點指定。

例如:

 <uniqueKey>id</uniqueKey>

defaultSearchField節點

默認搜索的字段,我們已經將需要搜索的字段拷貝至all字段了,在這裏設為all即可。

1 <defaultSearchField>all</defaultSearchField>

solrQueryParser節點

默認搜索操作符參數,及搜索短語間的邏輯,用AND增加準確率,用OR增加覆蓋面,建議用AND,也可在搜索語句中定義。例如搜索“河西 萬達”,使用AND默認搜索為“河西AND萬達“。

1 <solrQueryParser defaultOperator="OR"/> 

schema.xml的配置