Solr-全文檢索工具簡介

一.Solr的簡介

      Solr 是Apache下的一個頂級開源項目,採用Java開發,它是基於Lucene的全文搜索服務。Solr能夠獨立運行在Jetty、Tomcat等這些Servlet容器中。都是Web服務器,Servlet容器,報文 ,JSON 格式字符串, XML格式字符串。Solr是一個能夠獨立運行的搜索服務器,使用solr進行全文檢索服務的話,只須要經過http請求訪問該服務器便可。java

使用Solr 進行建立索引和搜索索引的實現方法很簡單,以下:node

  • 建立索引:客戶端(能夠是瀏覽器能夠是Java程序)用 POST 方法向 Solr 服務器發送一個描述 Field 及其內容的 XML 文檔,Solr服務器根據xml文檔添加、刪除、更新索引 。 
  • 搜索索引:客戶端(能夠是瀏覽器能夠是Java程序)用 GET方法向 Solr 服務器發送請求,而後對 Solr服務器返回Xml、json等格式的查詢結果進行解析。Solr不提供構建頁面UI的功能。Solr提供了一個管理界面,經過管理界面能夠查詢Solr的配置和運行狀況。

二.Solr和Lucene的區別

      Lucene是一個開放源代碼的全文檢索引擎工具包,它不是一個完整的全文檢索應用。Lucene僅提供了完整的查詢引擎和索引引擎,目的是爲軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者以Lucene爲基礎構建全文檢索應用。apache

      Solr的目標是打造一款企業級的搜索引擎系統,它是基於Lucene一個搜索引擎服務,能夠獨立運行,經過Solr能夠很是快速的構建企業的搜索引擎,經過Solr也能夠高效的完成站內搜索功能。json

三.Solr的單機與集羣概念

1.Solr的單機版

       概念:HttpSolrServer瀏覽器

2.Solr的集羣版

        概念:SolrCloud(solr 雲)是Solr提供的分佈式搜索方案,當你須要大規模,容錯,分佈式索引和檢索能力時使用 SolrCloud。當一個系統的索引數據量少的時候是不須要使用SolrCloud的,當索引量很大,搜索請求併發很高,這時須要使用SolrCloud來知足這些需求服務器

        結構:SolrCloud爲了下降單機的處理壓力,須要由多臺服務器共同來完成索引和搜索任務。實現的思路是將索引數據進行Shard(分片)拆分,每一個分片由多臺的服務器共同完成,當一個索引或搜索請求過來時會分別從不一樣的Shard的服務器中操做索引。SolrCloud須要Solr基於Zookeeper部署,Zookeeper是一個集羣管理軟件,因爲SolrCloud須要由多臺服務器組成,由zookeeper來進行協調管理。併發

一個collection能夠把數據(索引文件)拆分紅多份,放進幾個不一樣的shard中,一個shard的數據能夠有多個備份(replica)。一個shard的多個replica中會有一個leader,由選舉程序推選出來。一個replica至關於一個core。
 
這個功能的主要特性是:
  • 整個集羣的配置信息能夠集中配置
  • 對於搜索自動負載均衡、出現故障時能夠自動切換
  • 集成了ZooKeeper,負責集羣的協調和配置

 
如上圖,一個collection(collection1)被拆分到兩個不一樣的shard中,而每一個shard都有兩個服務器(node)提供負載均衡和遇錯切換的服務。這個分佈式的結構是由ZooKeeper負責管理的。那些node中,實心圓圈的就是leader。
 
相關概念:
  • HA:High Availability
  • Node:一個服務器、或虛擬服務器節點,每一個node對應一個port向外提供服務。對應於一個JVM。
  • Collection:一個SolrCloud實例,負責對一批數據創建一個索引,並提供基於這個索引的搜索服務
  • Shard:一個SolrCloud中的索引能夠被拆分存放到多個shard中
  • Replica:一個shard中的數據,能夠有多個副本,就是Replica,其中有一個被推選出來的leader
  • Core:負責處理一個Replica,跟一個node對應
  • Cluster:由ZooKeeper管理的多個Node的集合,對solr的請求能夠發送給一個cluster
Shard的數量決定了索引是若是被拆分的,因此,當一個cluster初始化完成以後,shard的數量是不能改的。
建立一個新的core並加入到一個Collection和shard中:
 
Shard的遷移:
若是原來只有一個機器、或只有少許機器,能夠先規劃好shard的數量並啓動,而後等有新的機器以後,在新的機器中爲某個shard啓動一個新的replica,而後把原來的shard移除,這樣ZooKeeper就會把新的replica提高爲這個shard的leader了。
 
Leader和Replica:
若是Solr啓動的時候,參數numShards=2,那麼前兩個啓動的node就是leader,分別服務於這兩個shard,第三個和以後啓動的node就是replica,他們會依次按照那兩個leader加入cluster的順序分配給那兩個leader(使用round-robin的方式)。也能夠在啓動node的時候使用shardId參數直接把這個node分配給某個shard。當solr重啓的時候,全部的node仍是歸屬到重啓以前所歸屬的shard,同個shard中先啓動的node就是leader(first come first served)。
當一個leader沒法工做的時候,這個shard中的某一個replica會被自動推選爲leader。在Solr Admin UI界面中,Cloud菜單裏面能夠看到哪一個是Leader(實心圓圈者)。
 
新的文檔能夠被送往任何一個node,SolrCloud會自動把它們分配到合適的shard中:
  • 若是文檔被送到一個replica中,那麼這個replica會把這些文檔發送給這個shard的leader
  • 當一個leader接收到文檔的時候,SolrCloud會決定這些文檔應該分配到哪一個shard,而後把它們發生給這個shard的leader、創建索引、並把索引起送給這個shard中全部的replica
添加shard:
若是須要加多一個shard,可使用Collections API,建立兩個新的shard,再把現有shard中的索引分配到這兩個新Shard中。舊的shard須要手動刪掉。

 

複製代碼
package com.xyg.solrj;

import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.junit.Test;

/**
 * <p>Title:SolrjDemo</p>
 * @Description:solrj的入門程序
 * @Param:
 * @Return:
 * @Author:Administrator
 * @Date:2017年11月3日上午12:32:42
 */
public class SolrjDemo {
    //添加  修改
    @Test
    public void testCreateAndUpdateIndex() throws Exception {
        // 1. 建立HttpSolrServer對象
        // 設置solr服務接口,瀏覽器客戶端地址http://127.0.0.1:8080/solr/#/
        String baseURL = "http://127.0.0.1:8080/solr";
        //String baseURL = "http://localhost:8080/solr/collection2";
        SolrServer solrServer = new HttpSolrServer(baseURL);
        // 2. 建立SolrInputDocument對象
        SolrInputDocument document = new SolrInputDocument();
        document.addField("id", "100");
        document.addField("name", "Hello world!");
        // 3. 把SolrInputDocument對象添加到索引庫中
        solrServer.add(document); //httpSolrServer.add(document,1000);
        // 4. 提交
        solrServer.commit();
    }    
    //刪除
    @Test
    public void testDeleteIndex() throws Exception {
        String baseURL = "http://127.0.0.1:8080/solr";        
        SolrServer  solrServer = new HttpSolrServer(baseURL);
        // 根據id刪除索引數據
        //solrServer.deleteById("100");
        // 根據條件刪除(若是是*:*就表示所有刪除,慎用)
        //solrServer.deleteByQuery("name:Hello");
        solrServer.deleteByQuery("*:*");  //刪除全部        
        solrServer.commit();  // 提交
    }
    //查詢
    @Test
    public void testSearchIndex1() throws Exception {
        String baseURL = "http://127.0.0.1:8080/solr";        
        SolrServer  solrServer = new HttpSolrServer(baseURL);
        // 建立搜索對象
        SolrQuery query = new SolrQuery();
        // 設置搜索條件
        query.setQuery("*:*");
        // 發起搜索請求
        QueryResponse response = solrServer.query(query);
        // 處理搜索結果
        SolrDocumentList docs = response.getResults();
        System.out.println("搜索到的結果總數:" + docs.getNumFound());
        // 遍歷搜索結果
        for (SolrDocument doc : docs) {
        System.out.println("----------------------------------------------------");
        System.out.println("id:" + doc.get("id"));
        System.out.println("name:" + doc.get("name"));
        }
    }        
    //複雜查詢索引
    @Test
    public void queryIndex2() throws Exception {
        //建立鏈接
        SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr");
        //建立一個query對象
        SolrQuery solrQuery = new SolrQuery();
        //設置關鍵詞查詢條件
        solrQuery.setQuery("鑽石");   //solrQuery.set("q","鑽石");        
        //過濾條件
        solrQuery.setFilterQueries("product_catalog_name:幽默雜貨");
        //排序條件
        solrQuery.setSort("product_price", ORDER.asc);
        //分頁處理
        solrQuery.setStart(0);
        solrQuery.setRows(10);
        //結果中域的列表        solrQuery.setFields("id","product_name","product_price","product_catalog_name","product_picture");
        //設置默認搜索域
        solrQuery.set("df", "product_keywords");
        //高亮顯示
        solrQuery.setHighlight(true);
        //高亮顯示的域
        solrQuery.addHighlightField("product_name");
        //高亮顯示的前綴
        solrQuery.setHighlightSimplePre("<font color='red'>");
        //高亮顯示的後綴
        solrQuery.setHighlightSimplePost("</font>");
        //執行查詢
        QueryResponse queryResponse = solrServer.query(solrQuery);
        //取查詢結果
        SolrDocumentList solrDocumentList = queryResponse.getResults();
        //共查詢到商品數量
        System.out.println("共查詢到商品數量:" + solrDocumentList.getNumFound());
        //遍歷查詢的結果
        for (SolrDocument solrDocument : solrDocumentList) {
            System.out.println(solrDocument.get("id"));
            //取高亮顯示
            String productName = "";
            Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
            List<String> list = highlighting.get(solrDocument.get("id")).get("product_name");
            //判斷是否有高亮內容
            if (null != list) {
                productName = list.get(0);
            } else {
                productName = (String) solrDocument.get("product_name");
            }                
            System.out.println(productName);
            System.out.println(solrDocument.get("product_price"));           
System.out.println(solrDocument.get("product_catalog_name")); System.out.println(solrDocument.get("product_picture")); } } }
複製代碼
相關文章
相關標籤/搜索