什么是Solr搜索
我們經常會用到搜索功能,所以也比較熟悉,這里就簡單的介紹一下搜索的原理。
當然只是介紹solr的原理,並不是搜索引擎的原理,那會更復雜。
流程圖
這是一個非常簡單的流程圖:
User:即需要搜索的用戶。
Raw Data:需要搜索的內容,當然是源數據,可能是文本文件,可能是數據庫的數據,可能是XML等等。
Index:有格式的數據。
其實從圖中可以看出來:
- Solr搜索非常類似於讀寫數據庫的過程。
-
Solr搜索最主要的兩個問題(細節已經封裝好):
- 怎樣從元數據合理組織格式化成Index
- 怎樣根據關鍵字從Index中調取相關數據(排序、模糊查詢等等)。
類比一下,Index就相當於數據表,里面有很多記錄,我們需要做的就是設計數據表的格式,有哪些列。並且根據關鍵字搜索。
Solr綜述
Solr其實是一個WebApp,在官網下載后將war包放在web'容器下便可以直接運行,你自己的web項目通過HTTP請求的方式和Solr交互。當然需要現在Solr中生成索引庫(類似不同的數據表)。HTTP請求中帶有相關參數(關鍵字、需要搜索的索引庫、排序規則….)。那么想愛先簡單介紹下一些相關的概念:
索引Index,文檔Docements,域Fields
Solr中數據最小單元為Field,比如Name、Age。Documents是一個具體的對象,如人。舉例說明:Edwin是一個人,那么可以將Edwin抽象為一個Document,這個Document包含很多Fields,Name、Age、Sex….。一個索引庫Index由許多Documents組成。
Index(Student) ß Docements(Edwin、AngelaBaby…) ß Fields(Name、Age…)
是不是很像數據庫的模型? 其實完全可以把這個理解為數據庫… 並且Index還真的有主鍵的概念,叫做Unique Field。
查詢Query
上面解決了數據格式化成Index的問題,那么還剩下怎樣根據關鍵字查詢搜索結果的問題,先舉個例子:
http://localhost:8983/solr/Artist/select?q=Artist_Name:周傑倫 &wt=json&indent=true
這就是web項目和Solr交互的一個Url
Localhost:8983/solr 這個事Solr項目
Artist是索引庫Index
q=Artist_Name:周傑倫
q代表Query 意思是查詢Artist_Name為周傑倫的數據
wt=json 指結果按照Json形式返回
indent=true 返回的數據格式化(也就是好看一點~)
通過這一個簡單的請求,即可以明白Solr請求的一個基本過程了,有什么需求加什么參數,之后Solr解析請求,根據自己的匹配規則,一個很復雜的公式,計算所有Documents的得分,得分高的優先返回。最后Web項目獲得得到搜索結果,格式化輸出。
兩個重要的文件
Schema.xml
這個文件其實就是對Index的配置,包括Field的類型,Unique Field,分詞等等。
先看看整體結構:
-
-
<schema name="Artist" version="1.1">
-
<fieldtype name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
-
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
-
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
-
<field name="ID" type="int" indexed="true" stored="true" multiValued="false" required="true"/>
-
<field name="Name" type="text_ik" indexed="true" stored="true"/>
-
<field name="Name_Exact" type="string" indexed="true" stored="true" />
-
<field name="SpaceID" type="long" indexed="true" stored="true"/>
-
<field name="PinYin" type="text_general" indexed="true" stored="true"/>
-
<field name="SongNum" type="int" indexed="true" stored="true"/>
-
-
<copyField source="Artist_Name" dest="Artist_Name_Exact" />
-
<!-- field to use to determine and enforce document uniqueness. -->
-
<uniqueKey>ID</uniqueKey>
-
-
<!-- field for the QueryParser to use when an explicit fieldname is absent -->
-
<defaultSearchField>ID</defaultSearchField>
-
-
<!-- Chinese -->
-
<fieldType name="text_ik" class="solr.TextField">
-
<analyzer type="index" isMaxWordLength="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
-
<analyzer type="query" isMaxWordLength="true" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
-
</fieldType>
-
-
<!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
-
<solrQueryParser defaultOperator="OR"/>
-
</schema>
FieldType代表Field的類型,可以自定義也可以使用Solr提供的Type,具體支持的Type可以參考Solr文檔,其中需要稍微解釋一下的是string,實現的class是solr.StrField,string的意思是將Field當成字符串,那么如果在搜索時,不會進行分詞。只能整體匹配,例如將Name設置為string,那么當搜索周傑倫的時候,只有Name完全和周傑倫相同才會被匹配,周傑,周傑倫你好…這些都不會匹配,這個在精確查找時很有用。
Unique Field :其實是主鍵的意思,就是說在所有的Documents中被設置成Unique的Field只能有唯一值。當然在Index生成的時候,不用去重,Solr並不會報錯,比如向Solr輸入
ID:1 Name:張三
ID:1 Name:李四
如果ID為Unique Field,那么Solr可能會根據先后順序,只會存儲一個ID為1的Document,剩余重復ID的Document會被忽略。
Field中還有很多屬性:
Name和Type就不說了
Indexed:表示此Field是否索引,意思就是能否被搜索到,如果Name設置為false,那么搜索Name=周傑倫是沒有結果的。
Stored:表示此Field是否被存儲。
multiValued:表示此Field能否有多值,即Category可以有多個值:如原創歌手、華語男歌手等等。默認false,Unique Field必須顯式設置為false。
Required:表示此Field是否能為空,默認false,Unique Field必須設置為true。
-
<copyField source="Name" dest="Name_Exact" />
這是一個很有用的東西,從名字就能看出來是賦值Field,最大的作用便是可以讓一個Field有多個不同的Type。
比如Name一個可以設置為text_ik(分詞器,可以看我的博客:三、Solr多核心及分詞器(IK)配置)
一個設置為string
那么模糊搜索時,可以使用Name,精確搜索時使用Name_Exact。
Solrconfig.xml
Scheme.xml是對索引庫中Documents的配置,那么solrconfig就是對索引庫的整體配置。配置requestHandler,有點類似於filter,就是在請求前后對請求進行預處理。這個之后碰到具體情況再具體分析,因為一般情況下設置好了之后,極少需要改動此文件。
總結
其實我個人使用Solr后覺得,如上面畫的簡單的流程圖,最重要的兩個問題:
-
查詢條件
查詢哪些Field,用什么方式查詢,什么排序,比如按照更新時間排序,還是在搜索歌曲時HQ、SQ優先等等,主要用到了Url參數、solrconfig中的requestHandler。
-
Index的設計
這是重中之重,我覺得大部分情況下應該都是使用solr從數據庫中讀取數據生成索引,這就要求原來的數據庫設計就要比較合理,如果原來的數據庫比較亂,那么就需要大量的SQL將表聯結等等操作,並且出錯的概率也高。