全文檢索技術——Solr
1、站內搜索技術選型
2、什麼是solr
Solr和lucene的區別
3、solr服務器的安裝及配置
Solr整合tomcat
Solr的演示
4、維護索引
創建索引
刪除索引
更新索引
5、索引的查詢
6、Solr的客戶端SolrJ
維護索引
查詢索引
1、使用Lucene來實現:需要大量的編碼才能實現。集群方案需要自己解決。查詢速度的優化都需要自己解決。不推薦使用。
2、使用搜素引擎提供的接口實現站內搜索。索引庫在搜索引擎上,維護不方便。開發簡單。
3、使用Solr來實現站內搜索。可以獨立運行,提供全套的解決方案。Solr集群、索引庫的優化。推薦使用。
Solr 是Apache下的一個頂級開源項目,采用Java開發,它是基於Lucene的全文搜索服務器。Solr提供了比Lucene更為豐富的查詢語言,同時實現了可配置、可擴展,並對索引、搜索性能進行了優化。
Solr可以獨立運行,運行在Jetty、Tomcat等這些Servlet容器中,Solr 索引的實現方法很簡單,用 POST 方法向 Solr 服務器發送一個描述 Field 及其內容的 XML 文檔,Solr根據xml文檔添加、刪除、更新索引 。Solr 搜索只需要發送 HTTP GET 請求,然後對 Solr 返回Xml、json等格式的查詢結果進行解析,組織頁面布局。Solr不提供構建UI的功能,Solr提供了一個管理界面,通過管理界面可以查詢Solr的配置和運行情況。
Lucene是一個開放源代碼的全文檢索引擎工具包,它不是一個完整的全文檢索引擎,Lucene提供了完整的查詢引擎和索引引擎,目的是為軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者以Lucene為基礎構建全文檢索引擎。
Solr的目標是打造一款企業級的搜索引擎系統,它是一個搜索引擎服務,可以獨立運行,通過Solr可以非常快速的構建企業的搜索引擎,通過Solr也可以高效的完成站內搜索功能。
下載地址:lucene.apache.org/solr/mirrors-solr-latest-redir.html?
版本是:4.10.4
Solr4.10要求jdk1.7.0及以上版本
要求tomcat7.0以上
第一步:安裝tomcat,我們使用的版本是apache-tomcat-7.0.67
第二步:部署solr的war包。將solr-4.10.4.war復制到tomcat的webapp下。改名為solr.war
第三步:解壓Solr.war,在solr\WEB-INF\lib添加日志需要的jar包。
將solr-4.10.4\example\lib\ext目錄下的jar復制到lib下。
第四步:配置solrhome,及solrcore。
Solrhome也就是solr服務器所有配置文件存放的文件夾。
\solr-4.10.4\example\solr文件夾就是一個標准的solrhome。
1)solr文件夾復制到指定位置E:\B_develop\apache-tomcat-7.0.67\webapps\solr\solrhome
2)Solrcore:collection1就是一個solrcore,一個solrcore就是一個索引庫。可以對比mysql的數據庫,一個solrcore相當於一個mysql 的數據庫。索引庫和索引庫之間相互獨立。
3)collection1\conf:每個sorlcore的配置信息。
4)Solrconfig.xml:solrcore的配置,如果使用默認配置可以不用修改。
luceneMatchVersion:匹配的lucene的版本
Lib:solrcore擴展包的位置,默認是collection1\lib文件夾,如果沒有lib文件夾就創建一個。
dataDir:索引庫存放的位置。默認是collection1\data文件夾,如果沒有sorl會自動創建。
查詢索引使用的URL:
<requestHandler name="/select" class="solr.SearchHandler">
維護索引使用的url:
<requestHandler name="/update" class="solr.UpdateRequestHandler">
默認查詢條件:
<defaultQuery>*:*</defaultQuery>
第五步:將solrhome的位置告訴solr服務。使用jndi的方式。修改web.xml文件
修改solrhome
第六步:啟動tomcat
第七步:訪問solr服務http://localhost:8088/solr
第一步:復制collection1為collection2
第二步:修改core.properties文件將name=collection2
第三步:重啟tomcat
在下拉框中選型要查看或者維護的solrcore
可以講關系型數據庫中的數據導入到索引庫中。
在schema.xml定義域及域的類型,必須先定義後使用。
Name:域的名字
Type:域的類型,可以可以自定義。也是在schema.xml中定義。
Indexed:是否索引
Stored:是否存儲
multiValued:是否多值,就是在一個域中存儲多個值,存儲一個數組。
如果一個未定義的域可以和動態域相匹配那麼也是可以使用的。
Name:動態域的表達式
Type:域的類型
Indexed:是否索引
Stored:是否存儲
multiValued:是否多值,就是在一個域中存儲多個值,存儲一個數組。
索引庫的主鍵。
每個文檔必須包含id域。
Source:源域
Dest:目標域
當向索引庫中添加文檔時,copyfield會自動將源域的內容復制到目標域中。
例如:
<copyField source="cat" dest="text"/>
Name:域類型的名稱
Class:實際對應的java類型
Analyzer:可以配置第三方分析器。可以自定義數據類型配置中文分析器。
修改schema.xml先添加fieldType然後再添加field。
第一步:先將IKAnalyzer的jar包添加到solr工程中(2012那個版本用在solr4.10.4不行)。
第二步:把配置文件復制到solr工程的classpath下。
第三步:修改collection1\conf\schema.xml添加自定義的fieldtype。
<!--IKAnalyzer --> <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>
第四步:在schema.xml添加自定義的域field。在120行附近更改type
<field name="name" type="text_ik" indexed="true" stored="true"/> <field name="manu" type="text_ik" indexed="true" stored="true" omitNorms="true"/>
第五步:重啟tomcat
<!--product-->
<field name="product_name" type="text_ik" indexed="true" stored="true"/>
<field name="product_price" type="float" indexed="true" stored="true"/>
<field name="product_description" type="text_ik" indexed="true" stored="false" />
<field name="product_picture" type="string" indexed="false" stored="true" />
<field name="product_catalog_name" type="string" indexed="true" stored="true" />
<field name="product_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="product_name" dest="product_keywords"/>
<copyField source="product_description" dest="product_keywords"/>
和商品表的表結構對應。
{"id":"a0001","title_ik":"中文分析器的title","content_ik":"接下來點擊頂部導航的“搜索框樣式”,進入搜索框設置界面。"}
先刪除後添加。
只需要再添加一個id和需要更新的文檔id一致新文檔就可以了。
第一步:先將插件依賴的jar包添加到solrcore中。放到Collection1\lib下。
第二步:mysql數據庫的驅動也添加到Collection1\lib下
第三步:修改solrconfig.xml配置文件。
<!--數據導入dataimport--> <requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler"> <lst name="defaults"> <str name="config">data-config.xml</str> </lst> </requestHandler>
第四步:創建data-config.xml文件放到collection\conf文件夾下。
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://10.7.4.6:3306/apolloagent"
user="root"
password="root"/>
<document>
<entity name="task" query="select id, workorderid, errorinfo, progress, priority, `handler` from task ">
<field column="id" name="id"/><!--id必須配置-->
<field column="workorderid" name="task_workorderid"/>
<field column="errorinfo" name="task_errorinfo"/>
<field column="progress" name="task_progress"/>
<field column="priority" name="task_priority"/>
<field column="handler" name="task_handler"/>
</entity>
</document>
</dataConfig> </dataConfig>
在schema.xml中增加field映射索引項
<field name="task_workorderid" type="string" indexed="true" stored="true"/>
<field name="task_errorinfo" type="string" indexed="true" stored="true"/>
<field name="task_progress" type="string" indexed="true" stored="true"/>
<field name="task_priority" type="string" indexed="true" stored="true"/>
<field name="task_handler" type="string" indexed="true" stored="true"/>
第五步:重啟tomcat。
先清空索引庫然後再倒入。
Request-Handler:/select
Q:查詢條件。默認是*:*。完全支持lucene的查詢語法,並且范圍查詢語法支持數值類型的域。
Fq:過濾查詢條件。是在查結果基礎上,進一步過濾。查詢語法和查詢條件的語法一致。
Sort:排序。指定排序的域在後面跟上asc|desc 。如果多個排序條件,使用半角逗號“,”分隔。
分頁處理:
Start:起始記錄的下標。
Row:每頁顯示的記錄數。
Fl:返回結果中文檔包含的域列表。多個域使用半角逗號“,”分隔。不設置此屬性默認返回全部域。
Df:默認搜索域。如果查詢條件中不指定搜索的域,而且不設置默認搜索域,就查詢不到結果。
Wt:返回結果的數據格式。可以是json、xml
Hl:高亮顯示
1)hl.fl:高亮顯示的域
2)Hl.simple.pre:前綴
3)Hl.simple.post:後綴
索引的增刪改操作。
第一步:創建一個java工程
第二步:導入jar包。
第三步:創建和服務端的連接。SolrServer對象,HttpSolrServer創建連接。
第四步:創建一個文檔對象。SolrInputDocument。
第五步:向文檔對象中添加域。
第六步:把文檔對象發送給服務端。
第七步:關閉連接。
代碼實現
//添加文檔
@Test
public void addDocument() throws Exception {
//建立連接
//參數是solr服務器的地址
SolrServer server = new HttpSolrServer("http://localhost:8080/solr");
//創建文檔對象
SolrInputDocument document = new SolrInputDocument();
//添加域,域名必須是schema.xml中定義的。而且必須有id這個域。
document.addField("id", "a001");
document.addField("title_ik", "新添加的文檔");
document.addField("content_ik", "新添加文檔的內容");
document.addField("product_name", "還沒想好叫什麼名字");
//把文檔添加到索引庫
server.add(document);
//提交修改
server.commit();
}
//刪除文檔
@Test
public void deleteDocument() throws Exception {
//建立連接
//參數是solr服務器的地址
SolrServer server = new HttpSolrServer("http://localhost:8080/solr");
//刪除指定id的文檔
server.deleteById("a001");
//提交
server.commit();
}
沒有專門的修改文檔的方法,直接在添加一條新的文檔,要求id和需要更新的文檔id保持一致就可以了。
跟添加文檔的方法一樣。
//查詢索引庫
@Test
public void searchIndex() throws Exception {
//建立連接
SolrServer server = new HttpSolrServer("http://localhost:8080/solr");
//創建一個query對象
SolrQuery query = new SolrQuery();
//查詢條件
query.setQuery("花兒");
//過濾條件
query.addFilterQuery("product_price:[10 TO 100]");
//排序
query.setSort("product_price", ORDER.asc);
//分頁處理
query.setStart(0);
query.setRows(10);
//文檔中包含的域列表
query.setFields("product_picture", "product_catalog_name", "product_price", "product_name", "id");
//設置默認搜索域
query.set("df", "product_keywords");
//高亮設置
query.setHighlight(true);
//高亮顯示的域
query.addHighlightField("product_name");
//設置高亮前綴
query.setHighlightSimplePre("<em>");
//高亮後綴
query.setHighlightSimplePost("</em>");
//執行查詢
QueryResponse queryResponse = server.query(query);
//取查詢結果
SolrDocumentList solrDocumentList = queryResponse.getResults();
//獲得查詢結果的總數量
System.out.println("查詢結果的總數量" + solrDocumentList.getNumFound());
//遍歷查詢結果
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
System.out.println(solrDocument.get("product_picture"));
System.out.println(solrDocument.get("product_catalog_name"));
System.out.println(solrDocument.get("product_price"));
//取高亮顯示
String name = "";
//取高亮內容
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
List<String> list = highlighting.get(solrDocument.get("id")).get("product_name");
if (null == list) {
name = (String) solrDocument.get("product_name");
} else {
name = list.get(0);
}
System.out.println(name);
}
}