1. Solr的簡介
Solr是一個獨立的企業級搜索應用服務器,它對外提供類似於Web-service的API接口。用戶可以通過http請求,向搜索引擎服務器提交一定格式的XML文件,生成索引;也可以通過Http Get操作提出查找請求,並得到XML格式的返回結果。
Solr是Apache軟件基金會下的子項目之一。
2. 工作原理
solr是基於Lucence開發的企業級搜索引擎技術,而lucence的原理是倒排索引。那麼什麼是倒排索引呢?接下來我們就介紹一下lucence倒排索引原理。
假設有兩篇文章1和2:
文章1的內容爲:老超在卡子門工作,我也是。
文章2的內容爲:小超在鼓樓工作。
由於lucence是基於關鍵詞索引查詢的,那我們首先要取得這兩篇文章的關鍵詞。如果我們把文章看成一個字符串,我們需要取得字符串中的所有單詞,即分詞。分詞時,忽略”在“、”的“之類的沒有意義的介詞,以及標點符號可以過濾。
我們使用Ik Analyzer實現中文分詞,分詞之後結果爲:
文章1:
文章2:
接下來,有了關鍵詞後,我們就可以建立倒排索引了。上面的對應關係是:“文章號”對“文章中所有關鍵詞”。倒排索引把這個關係倒過來,變成: “關鍵詞”對“擁有該關鍵詞的所有文章號”。
文章1、文章2經過倒排後變成:
通常僅知道關鍵詞在哪些文章中出現還不夠,我們還需要知道關鍵詞在文章中出現次數和出現的位置,通常有兩種位置:
a.字符位置,即記錄該詞是文章中第幾個字符(優點是關鍵詞亮顯時定位快);
b.關鍵詞位置,即記錄該詞是文章中第幾個關鍵詞(優點是節約索引空間、詞組(phase)查詢快),lucene中記錄的就是這種位置。
加上出現頻率和出現位置信息後,我們的索引結構變爲:
實現時,lucene將上面三列分別作爲詞典文件(Term Dictionary)、頻率文件(frequencies)、位置文件 (positions)保存。其中詞典文件不僅保存有每個關鍵詞,還保留了指向頻率文件和位置文件的指針,通過指針可以找到該關鍵字的頻率信息和位置信息。
3. 使用SolrJ管理索引庫
使用SolrJ可以實現索引庫的增刪改查操作。
3.1 添加文檔
第一步:把solrJ的jar包添加到工程中。
第二步:創建一個SolrServer,使用HttpSolrServer創建對象。
第三步:創建一個文檔對象SolrInputDocument對象。
第四步:向文檔中添加域。必須有id域,域的名稱必須在schema.xml中定義。
第五步:把文檔添加到索引庫中。
第六步:提交。
@Test
public void testSolrJAdd() throws SolrServerException, IOException {
// 創建一個SolrServer對象。創建一個HttpSolrServer對象
// 需要指定solr服務的url
SolrServer solrServer = new HttpSolrServer("http://101.132.69.111:8080/solr/collection1");
// 創建一個文檔對象SolrInputDocument
SolrInputDocument document = new SolrInputDocument();
// 向文檔中添加域,必須有id域,域的名稱必須在schema.xml中定義
document.addField("id", "123");
document.addField("item_title", "紅米手機");
document.addField("item_price", 1000);
// 把文檔對象寫入索引庫
solrServer.add(document);
// 提交
solrServer.commit();
}
3.2 刪除文檔
3.2.1 根據id刪除
第一步:創建一個SolrServer對象。
第二步:調用SolrServer對象的根據id刪除的方法。
第三步:提交。
@Test
public void deleteDocumentById() throws Exception {
SolrServer solrServer = new HttpSolrServer("http://101.132.69.111:8080/solr/collection1");
solrServer.deleteById("123");
// 提交
solrServer.commit();
}
3.2.2 根據查詢刪除
@Test
public void deleteDocumentByQuery() throws Exception {
SolrServer solrServer = new HttpSolrServer("http://101.132.69.111:8080/solr/collection1");
//這邊會根據分詞去刪
solrServer.deleteByQuery("item_title:紅米手機");
solrServer.commit();
}
3.3 查詢索引庫
第一步:創建一個SolrServer對象
第二步:創建一個SolrQuery對象。
3 向SolrQuery中添加查詢條件、過濾條件。。。
第四步:執行查詢。得到一個Response對象。
5 取查詢結果。
第六步:遍歷結果並打印。
3.3.1 簡單查詢
@Test
public void queryDocument() throws Exception {
// 第一步:創建一個SolrServer對象
SolrServer solrServer = new HttpSolrServer("http://101.132.69.111:8080/solr/collection1");
// 第二步:創建一個SolrQuery對象。
SolrQuery query = new SolrQuery();
// 第三步:向SolrQuery中添加查詢條件、過濾條件。。。
query.setQuery("*:*");
// 第四步:執行查詢。得到一個Response對象。
QueryResponse response = solrServer.query(query);
// 第五步:取查詢結果。
SolrDocumentList solrDocumentList = response.getResults();
System.out.println("查詢結果的總記錄數:" + solrDocumentList.getNumFound());
// 第六步:遍歷結果並打印。
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
System.out.println(solrDocument.get("item_title"));
System.out.println(solrDocument.get("item_price"));
}
}
3.3.2 帶高亮顯示
@Test
public void searchDocumet() throws Exception {
// 創建一個SolrServer對象
SolrServer solrServer = new HttpSolrServer("http://101.132.69.111:8080/solr/collection1");
// 創建一個SolrQuery對象
SolrQuery query = new SolrQuery();
// 設置查詢條件、過濾條件、分頁條件、排序條件、高亮
// query.set("q", "*:*");
query.setQuery("手機");
// 分頁條件
query.setStart(0);
query.setRows(30);
// 設置默認搜索域
query.set("df", "item_keywords");
// 設置高亮
query.setHighlight(true);
// 高亮顯示的域
query.addHighlightField("item_title");
query.setHighlightSimplePre("<div>");
query.setHighlightSimplePost("</div>");
// 執行查詢,得到一個Response對象
QueryResponse response = solrServer.query(query);
// 取查詢結果
SolrDocumentList solrDocumentList = response.getResults();
// 取查詢結果總記錄數
System.out.println("查詢結果總記錄數:" + solrDocumentList.getNumFound());
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
// 取高亮顯示
Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
String itemTitle = "";
if (list != null && list.size() > 0) {
itemTitle = list.get(0);
} else {
itemTitle = (String) solrDocument.get("item_title");
}
System.out.println(itemTitle);
System.out.println(solrDocument.get("item_sell_point"));
System.out.println(solrDocument.get("item_price"));
System.out.println(solrDocument.get("item_image"));
System.out.println(solrDocument.get("item_category_name"));
System.out.println("=============================================");
}
}
4. Solr服務器中的後臺數據處理
這個其實是通過圖形界面操作,只需手動填寫查詢條件,不需要進行代碼處理。但是實際項目開發中,還是需要進行代碼編寫的。
4.1 solr的基礎語法
q 查詢的關鍵字,此參數最爲重要,例如,q=id:1,默認爲q=*:*,
fq (filter query)過慮查詢,提供一個可選的篩選器查詢。
返回在q查詢符合結果中同時符合的fq條件的查詢結果
sort 排序方式,例如id desc 表示按照 “id” 降序
start 返回結果的第幾條記錄開始,一般分頁用,默認0開始
rows 指定返回結果最多有多少條記錄,默認值爲 10,配合start實現分頁
fl 指定返回哪些字段,用逗號或空格分隔,注意:字段區分大小寫,例如,fl= id,title,sort
df 默認的查詢字段,一般默認指定
wt (writer type)指定輸出格式,有 xml, json, php等
indent 返回的結果是否縮進,默認關閉
hl 高亮
hl.fl 設定高亮顯示的字段
hl.requireFieldMatch 如果置爲true,除非用hl.fl指定了該字段,查詢結果纔會被高亮。它的默認值是false。
hl.usePhraseHighlighter 如果一個查詢中含有短語(引號框起來的)那麼會保證一定要完全匹配短語的纔會被高亮。
hl.highlightMultiTerm如果使用通配符和模糊搜索,那麼會確保與通配符匹配的term會高亮。默認爲false,同時hl.usePhraseHighlighter要爲true。
hl.fragsize 返回的最大字符數。默認是100.如果爲0,那麼該字段不會被fragmented且整個字段的值會被返回。