Solr的工作原理以及如何管理索引庫

1. Solr的簡介

​ Solr是一個獨立的企業級搜索應用服務器,它對外提供類似於Web-service的API接口。用戶可以通過http請求,向搜索引擎服務器提交一定格式的XML文件,生成索引;也可以通過Http Get操作提出查找請求,並得到XML格式的返回結果。

​ Solr是Apache軟件基金會下的子項目之一。
Solr的工作原理以及如何管理索引庫

2. 工作原理

​ solr是基於Lucence開發的企業級搜索引擎技術,而lucence的原理是倒排索引。那麼什麼是倒排索引呢?接下來我們就介紹一下lucence倒排索引原理。

假設有兩篇文章1和2:

文章1的內容爲:老超在卡子門工作,我也是。

文章2的內容爲:小超在鼓樓工作。

由於lucence是基於關鍵詞索引查詢的,那我們首先要取得這兩篇文章的關鍵詞。如果我們把文章看成一個字符串,我們需要取得字符串中的所有單詞,即分詞。分詞時,忽略”在“、”的“之類的沒有意義的介詞,以及標點符號可以過濾。

我們使用Ik Analyzer實現中文分詞,分詞之後結果爲:

文章1:
Solr的工作原理以及如何管理索引庫

文章2:
Solr的工作原理以及如何管理索引庫

接下來,有了關鍵詞後,我們就可以建立倒排索引了。上面的對應關係是:“文章號”對“文章中所有關鍵詞”。倒排索引把這個關係倒過來,變成: “關鍵詞”對“擁有該關鍵詞的所有文章號”。

文章1、文章2經過倒排後變成:

Solr的工作原理以及如何管理索引庫

通常僅知道關鍵詞在哪些文章中出現還不夠,我們還需要知道關鍵詞在文章中出現次數和出現的位置,通常有兩種位置:

a.字符位置,即記錄該詞是文章中第幾個字符(優點是關鍵詞亮顯時定位快);

b.關鍵詞位置,即記錄該詞是文章中第幾個關鍵詞(優點是節約索引空間、詞組(phase)查詢快),lucene中記錄的就是這種位置。

加上出現頻率和出現位置信息後,我們的索引結構變爲:

Solr的工作原理以及如何管理索引庫

實現時,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服務器中的後臺數據處理

​ 這個其實是通過圖形界面操作,只需手動填寫查詢條件,不需要進行代碼處理。但是實際項目開發中,還是需要進行代碼編寫的。
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且整個字段的值會被返回。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章