1、solr介紹
a). 什么是solr b). Solr和lucene的區別
2、Solr的安裝配置(重點)
3、Solr的基本使用(重點)
4、Solrj的使用(重點)
5、京東案例(重點)
Solr是apache的頂級開源項目,它是使用java開發 ,基于lucene的全文檢索服務器。
Solr比lucene提供了更多的查詢語句,而且它可擴展、可配置,同時它對lucene的性能進行了優化。
Solr是如何實現全文檢索的呢?
索引流程: solr客戶端(瀏覽器、java程序)可以向solr服務端發送POST請求,請求內容是包含Field等信息的一個xml文檔,通過該文檔,solr實現對索引的維護(增刪改)
搜索流程: solr客戶端(瀏覽器、java程序)可以向solr服務端發送GET請求,solr服務器返回一個xml文檔。
Solr同樣沒有視圖渲染的功能。
Lucene 是一個全文檢索引擎工具包,它只是一個jar包,不能獨立運行,對外提供服務。
Solr 是一個全文檢索服務器,它可以單獨運行在servlet容器,可以單獨對外提供搜索和索引功能。Solr比lucene在開發全文檢索功能時,更快捷、更方便。  
Solr和lucene的版本是同步更新的,最新的版本是5.2.1 本課程使用的版本:4.10.3
下載地址:http://archive.apache.org/dist/lucene/solr/ 下載版本:4.10.3 linux下需要下載lucene-4.10.3.tgz,windows下需要下載lucene-4.10.3.zip。 
  
 

第一步:安裝tomcat 第二步:將以下的war包,拷貝到tomcat的webapps目錄下  
 第三步:解壓縮war包 解壓縮之后,將war包刪掉  
 第四步:添加solr的擴展服務包  
將以上jar包,添加到以下目錄 
 
第五步:添加log4j.PRoperties 將以下目錄的文件進行拷貝  
復制到以下目錄  
第六步:在web.xml中指定solrhome的目錄  
Solrhome是solr服務運行的主目錄,一個solrhome目錄里面包含多個solrcore目錄,一個solrcore目錄里面包含了一個solr實例運行時所需要的配置文件和數據文件。
每一個solrcore都可以單獨對外提供搜索和索引服務。 多個solrcore之間沒有關系。
Solrhome的目錄結構  
Solrcore目錄 
安裝solrcore需要先安裝solrhome
將以下目錄的文件進行拷貝 
復制到以下目錄  
這樣solrhome和solrcore就安裝成功了。
在solrcore的conf目錄下,有一個solrconfig.xml的配置文件,該配置文件,配置來solrcore的運行信息 
在該文件中,主要配置三個標簽:lib標簽、datadir標簽、requestHandler標簽
如果對該文件不進行配置也可以,即使用默認的配置項。
Solrcore需要添加一個擴展依賴包,通過lib標簽來指定依賴包的地址
solr.install.dir: 表示solrcore的安裝目錄
將以下目錄的文件進行拷貝 
復制到以下目錄 
修改lib標簽 
每個SolrCore都有自己的索引文件目錄 ,默認在SolrCore目錄下的data中。  
 data數據目錄下包括了index索引目錄 和tlog日志文件目錄。 如果不想使用默認的目錄也可以通過solrConfig.xml更改索引目錄 ,如下:  
requestHandler請求處理器,定義了索引和搜索的訪問方式。 通過/update維護索引,可以完成索引的添加、修改、刪除操作。  
 提交xml、json數據完成索引維護,索引維護小節詳細介紹。
通過/select搜索索引。 
 
設置搜索參數完成搜索,搜索參數也可以設置一些默認值,如下:
<requestHandler name="/select" class="solr.SearchHandler"> <!-- 設置默認的參數值,可以在請求地址中修改這些參數--> <lst name="defaults"> <str name="echoParams">explicit</str> <int name="rows">10</int><!--顯示數量--> <str name="wt">json</str><!--顯示格式--> <str name="df">text</str><!--默認搜索字段--> </lst></requestHandler>啟動solr服務 http://localhost:8080/solr 
儀表盤,顯示了該Solr實例開始啟動運行的時間、版本、系統資源、jvm等信息。
Solr運行日志信息
Cloud即SolrCloud,即Solr云(集群),當使用Solr Cloud模式運行時會顯示此菜單,該部分功能在第二個項目,即電商項目會講解。
Solr Core的管理界面。在這里可以添加SolrCore實例。
Solr在JVM 運行環境中的屬性信息,包括類路徑、文件編碼、jvm內存設置等信息。
顯示Solr Server中當前活躍線程信息,同時也可以跟蹤線程運行棧信息。
選擇一個SolrCore進行詳細操作,如下:  
 通過此界面可以測試索引分析器和搜索分析器的執行情況。 注:solr中,分析器是綁定在域的類型中的。
可以定義數據導入處理器,從關系數據庫將數據導入到Solr索引庫中。 默認沒有配置,需要手工配置。
通過/update表示更新索引,solr默認根據id(唯一約束)域來更新Document的內容,如果根據id值搜索不到id域則會執行添加操作,如果找到則更新。
通過此菜單可以創建索引、更新索引、刪除索引等操作,界面如下:  
通過/select執行搜索索引,必須指定“q”查詢條件方可搜索。 
配置多solrcore的好處: 1、 在進行solrcloud的時候,必須配置多solrcore 2、 每個solrcore之間是獨立的,都可以單獨對外提供服務。不同的業務模塊可以使用不同的solrcore來提供搜索和索引服務。
添加
第一步:復制solrhome下的collection1目錄到本目錄下,修改名稱為collection2 
第二步:修改solrcore目錄下的core.properties 
 這樣多solrcore就配置完成了。
在schema.xml文件中,主要配置了solrcore的一些數據信息,包括Field和FieldType的定義等信息,在solr中,Field和FieldType都需要先定義后使用。 
定義Field域
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />Name:指定域的名稱 Type:指定域的類型 Indexed:是否索引 Stored:是否存儲 Required:是否必須 multiValued:是否多值,比如商品信息中,一個商品有多張圖片,一個Field像存儲多個值的話,必須將multiValued設置為true。
動態域
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>Name:指定動態域的命名規則
指定唯一鍵
<uniqueKey>id</uniqueKey>其中的id是在Field標簽中已經定義好的域名,而且該域要設置為required為true。
一個schema.xml文件中必須有且僅有一個唯一鍵
復制域
<copyField source="cat" dest="text"/>Source: 要復制的源域的域名 Dest: 目標域的域名
由dest指的的目標域,必須設置multiValued為true。

定義域的類型
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100"> <analyzer type="index"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.StopFilterFactory" ignoreCase="true" Words="stopwords.txt" /> <!-- in this example, we will only use synonyms at query time <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/> --> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> <analyzer type="query"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" /> <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/> <filter class="solr.LowerCaseFilterFactory"/> </analyzer></fieldType>Name: 指定域類型的名稱 Class: 指定該域類型對應的solr的類型 Analyzer: 指定分析器 Type: index、query,分別指定搜索和索引時的分析器 Tokenizer: 指定分詞器 Filter: 指定過濾器
使用ikanalyzer進行中文分詞
第一步:將ikanalyzer的jar包拷貝到以下目錄

第二步:將ikanalyzer的擴展詞庫的配置文件拷貝到 目錄

第三步:配置FieldType

第四步:配置使用中文分詞的Field

第五步:重啟tomcat

對京東案例中的products表的數據進行索引,所以需要先定義對應的Field域。
Products的表結構  
需要往索引庫添加的字段有: pid、name、catalog、catalog_name、price、description、picture
FieldType: 經分析,由于中文分詞器已經配置完FieldType,所以目前FieldType已經滿足需要,無需配置。
Field: Pid: 由于pid在products表中是唯一鍵,而且在solr的shema.xml中已有一個id的唯一鍵配置,所以不需要再重新定義pid域。
Name:
<field name="product_name" type="text_ik" indexed="true" stored="true"/>Catalog、catalog_name:
<!-- 商品分類ID --><field name="product_catalog" type="string" indexed="true" stored="true"/> <!-- 商品分類名稱 --><field name="product_catalog_name" type="string" indexed="true" stored="false"/>Price:<!-- 商品價格 --><field name="product_price" type="float" indexed="true" stored="true"/>Description:<!-- 商品描述 --><field name="product_description" type="text_ik" indexed="true" stored="false"/>Picture:<!-- 商品圖片地址 --><field name="product_picture" type="string" indexed="false" stored="true"/>
該插件可以將數據庫中指定的sql語句的結果導入到solr索引庫中。
Dataimport的jar包 復制以下目錄的jar包 
添加到以下目錄 
修改solrconfig.xml文件,添加lib標簽
<lib dir="${solr.install.dir:../..}/contrib/dataimporthandler/lib" regex=".*/.jar" />MySQL數據庫驅動包 將mysql的驅動包,復制到以下目錄 
修改solrconfig.xml文件,添加lib標簽
<lib dir="${solr.install.dir:../..}/contrib/db/lib" regex=".*/.jar" />在solrconfig.xml中,添加一個dataimport的requestHandler 
在solrconfig.xml同級目錄下,創建data-config.xml 

Solrj就是solr服務器的java客戶端。 
 
Solrj的依賴包和核心包 
Solr的擴展服務包 
  
在solr中,索引庫中都會存在一個唯一鍵,如果一個Document的id存在,則執行修改操作,如果不存在,則執行添加操作。 
 



(1).    q - 查詢關鍵字,必須的,如果查詢所有使用:。 請求的q是字符串 
(2).    fq - (filter query)過慮查詢,作用:在q查詢符合結果中同時是fq查詢符合的,例如:: 請求fq是一個數組(多個值) 
過濾查詢價格從1到20的記錄。 也可以在“q”查詢條件中使用product_price:[1 TO 20],如下: 
也可以使用“*”表示無限,例如: 20以上:product_price:[20 TO *] 20以下:product_price:[* TO 20]
(3).    sort - 排序,格式:sort=<field name>+<desc|asc>[,<field name>+<desc|asc>]… 。 示例: 
 按價格降序 (4).    start - 分頁顯示使用,開始記錄下標,從0開始  (5).    rows - 指定返回結果最多有多少條記錄,配合start來實現分頁。 實際開發時,知道當前頁碼和每頁顯示的個數最后求出開始下標。
(6).    fl - 指定返回那些字段內容,用逗號或空格分隔多個。  
 顯示商品圖片、商品名稱、商品價格
(7).    df - 指定一個搜索Field 
 也可以在SolrCore目錄 中conf/solrconfig.xml文件中指定默認搜索Field,指定后就可以直接在“q”查詢條件中輸入關鍵字。 
(8). wt - (writer type)指定輸出格式,可以有 xml, json, php, phps, 后面 solr 1.3增加的,要用通知我們,因為默認沒有打開。
(9).    hl - 是否高亮 ,設置高亮Field,設置格式前綴和后綴。 
使用Solr實現電商網站中商品信息搜索功能,可以根據關鍵字、分類、價格搜索商品信息,也可以根據價格進行排序,同時還可以分頁。 界面如下: 

應用服務器服務端: 表現層:使用springmvc接收前臺搜索頁面的查詢條件等信息 業務層:調用dao層完成數據庫持久化 如果數據庫數據發生變化,調用solrj的客戶端同步索引庫。 Dao層:使用mybatis完成數據庫持久化
Solrj服務器: 提供搜索和索引服務
數據庫服務器: 提供數據庫服務


Service接口 
Service實現類
@Servicepublic class ProductServiceImpl implements ProductService { // 依賴注入HttpSolrServer @Autowired private HttpSolrServer server; @Override public ResultModel getProducts(String queryString, String catalogName, String price, String sort, Integer page) throws Exception { // 創建SolrQuery對象 SolrQuery query = new SolrQuery(); // 輸入關鍵字 if (StringUtils.isNotEmpty(queryString)) { query.setQuery(queryString); } else { query.setQuery("*:*"); } // 輸入商品分類過濾條件 if (StringUtils.isNotEmpty(catalogName)) { query.addFilterQuery("product_catalog_name:" + catalogName); } // 輸入價格區間過濾條件 // price的值:0-9 10-19 if (StringUtils.isNotEmpty(price)) { String[] ss = price.split("-"); if (ss.length == 2) { query.addFilterQuery("product_price:[" + ss[0] + " TO " + ss[1] + "]"); } } // 設置排序 if ("1".equals(sort)) { query.setSort("product_price", ORDER.desc); } else { query.setSort("product_price", ORDER.asc); } // 設置分頁信息 if (page == null) page = 1; query.setStart((page - 1) * 20); query.setRows(20); // 設置默認域 query.set("df", "product_keywords"); // 設置高亮信息 query.setHighlight(true); query.addHighlightField("product_name"); query.setHighlightSimplePre("<font style=/"color:red/" >"); query.setHighlightSimplePost("</font>"); QueryResponse response = server.query(query); // 查詢出的結果 SolrDocumentList results = response.getResults(); // 記錄總數 long count = results.getNumFound(); List<Products> products = new ArrayList<>(); Products prod; // 獲取高亮信息 Map<String, Map<String, List<String>>> highlighting = response .getHighlighting(); for (SolrDocument doc : results) { prod = new Products(); // 商品ID prod.setPid(doc.get("id").toString()); List<String> list = highlighting.get(doc.get("id")).get( "product_name"); // 商品名稱 if (list != null) prod.setName(list.get(0)); else { prod.setName(doc.get("product_name").toString()); } // 商品價格 prod.setPrice(Float.parseFloat(doc.get("product_price").toString())); // 商品圖片地址 prod.setPicture(doc.get("product_picture").toString()); products.add(prod); } // 封裝ResultModel對象 ResultModel rm = new ResultModel(); rm.setProductList(products); rm.setCurPage(page); rm.setRecordCount(count); int pageCount = (int) (count / 20); if (count % 20 > 0) pageCount++; // 設置總頁數 rm.setPageCount(pageCount); return rm; }}
從資料中拷貝 
 

圖片信息放到以下目錄




(歐了)
新聞熱點
疑難解答