solr 介紹
什麼是 solr
Solr是apache的頂級開源專案,它是使用java開發 ,基於lucene的全文檢索伺服器。
Solr比lucene提供了更多的查詢語句,而且它可擴充套件、可配置,同時它對lucene的效能進行了優化。
Solr是如何實現全文檢索的呢?
索引流程:solr客戶端(瀏覽器、java程式)可以向solr服務端傳送POST請求,請求內容是包含Field等資訊的一個xml文件,通過該文件,solr實現對索引的維護(增刪改)
搜尋流程:solr客戶端(瀏覽器、java程式)可以向solr服務端傳送GET請求,solr伺服器返回一個xml文件。
Solr同樣沒有檢視渲染的功能。
solr 和 lucene 的區別
Lucene 是一個全文檢索引擎工具包,它是一個 jar 包,不能獨立執行,對外提供服務。
Solr 是一個全文檢索伺服器,它可以單獨執行在 servlet 容器,可以單獨對外提供搜尋和索引功能。Solr 比 lucene 在開發全文檢索功能時,更快捷、更方便。
solr 的安裝配置
下載
solr 和 lucene 的版本時同步更新的,最新版本是5.2.1
下載地址:http://archive.apache.org/dist/lucene/solr/
環境
jdk:1.7及以上 solr:4.10.3 mysql:5x web伺服器:tomcat7
初始化資料庫指令碼
solr 安裝配置
- 安裝 tomcat
- 將solr-4.10.3\example\webapps 目錄下 solr.war 拷貝到 tomcat webapps 目錄下
- 解壓縮 war 包,解壓縮之後,將 war 包刪掉
- 新增 solr 擴充套件服務包。將 solr-4.10.3\example\lib\ext 目錄下 jar 拷貝到 tomcat solr WEB-INF lib 目錄下
- 新增 log4j.properties。拷貝 solr-4.10.3\example\resources 目錄下 log4j.properties 到 apache-tomcat-7.0.57\webapps\solr\WEB-INF\classes ,目錄不存在沒有則建立。
- 在 web.xml 中指定 solrhome 的目錄
solrcore 安裝
solrcore 和 solrhome
Solrhome是solr服務執行的主目錄,一個solrhome目錄裡面包含多個solrcore目錄,一個solrcore目錄裡面了一個solr例項執行時所需要的配置檔案和資料檔案。
每一個solrcore都可以單獨對外提供搜尋和索引服務。 多個solrcore之間沒有關係。
solrcore 和 solrhome 的目錄結構
solrhome: solr-4.10.3\example\solr solrcore: solr-4.10.3\example\solr\collection1 包含配置檔案,索引檔案日誌資訊
solrcore 的安裝
安裝 solrcore 需要先安裝 solrhome 將上面solrhome下的檔案拷貝到web.xml中指定的solrhome中即可
solrcore 的配置
配置 solrcore 的 conf 目錄下的 solrconfig.xml 配置檔案,來配置 solrcore 的執行資訊。
在該檔案中,主要配置三個標籤:lib 標籤、datadir標籤、requestHandler 標籤。
lib 標籤
solrcore 需要新增一個擴充套件依賴包,通過 lib 標籤來指定依賴包的地址
solr.install.dir 表示 solrcore 的安裝目錄
拷貝 example 目錄下的 contrib 和 dis 目錄到
修改 lib 標籤
datadir 標籤
每個 solrcore 都有自己的索引檔案目錄,預設在 solrcore 目錄下的 data 中。
data資料目錄下包括了index索引目錄 和tlog日誌檔案目錄。 如果不想使用預設的目錄也可以通過solrConfig.xml更改索引目錄 ,如下:
requestHandler 標籤
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 介面
Dashboard
儀表盤,顯示 solr 例項執行時間、版本、系統資源、jvm等資訊。 、
Logging
solr 執行日誌資訊
Cloud
Cloud即SolrCloud,即Solr雲(叢集),當使用Solr Cloud模式執行時會顯示此選單.
Core Admin
solrcore 的管理介面,這裡可以新增 solrcore 例項。
java properties
solr 在 jvm 執行環境中的屬性資訊。
Thread Dump
顯示 solr server 中當前活躍執行緒資訊,同時也可以跟蹤執行緒執行棧資訊。
Core selector
選擇一個 solrcore 進行詳細操作,如下:
Analysis
通過此介面可以測試索引分析器和搜尋分析器的執行情況。 注:solr 中,分析器是繫結在域型別中的。
dataimport
可以定義資料匯入處理器,從關聯式資料庫匯入到 solr 索引庫中。預設配置,需要手工配置。
Document
通過 /update 表示更新索引,solr 預設根據 id(唯一約束) 域來更新 document 的內容,如果根據 id 值搜尋不到 id 域則會執行新增操作,如果找到則更新。
通過此選單可以建立索引、更新索引、刪除索引等操作,介面如下:
- overwrite="true" : solr在做索引的時候,如果文件已經存在,就用xml中的文件進行替換
- commitWithin="1000" : solr 在做索引的時候,每個1000(1秒)毫秒,做一次文件提交。為了方便測試也可以在Document中立即提交,後新增“”
Query
通過/select執行搜尋索引,必須指定“q”查詢條件方可搜尋。
多 solrcore 配置
配置多solrcore的好處: 1、在進行 solrcloud 的時候,必須配置多solrcore 2、每個 solrcore 之間是獨立的,都可以單獨對外提供服務。不同的業務模組可以使用不同的solrcore 來提供搜尋和索引服務。
新增
- 第一步:複製 solrhome 下的 collection1 目錄到本目錄下,修改名稱為 collection2
- 修改 solrcore 目錄下的 core.properties 這樣多 solrcore 就配置完成了。
Solr 基本使用
schema.xml
在 schema.xml 檔案中,主要配置了 solrcore 的一些資料資訊,包括 Field 和 FieldType 的定義等資訊,在 solr 中,Field 和 FieldType 都需要先定義後使用。
Field
定義Field域
Name:指定域的名稱 Type:指定域的型別 Indexed:是否索引 Stored:是否儲存 Required:是否必須 multiValued:是否多值,比如商品資訊中,一個商品有多張圖片,一個Field像儲存多個值的話,必須將multiValued設定為true。
dynamicField
動態域
Name:指定動態域的命名規則
uniqueKey
指定唯一鍵
id
其中的id是在Field標籤中已經定義好的域名,而且該域要設定為required為true。
一個schema.xml檔案中必須有且僅有一個唯一鍵
copyField
複製域
Source:要複製的源域的域名 Dest:目標域的域名
由dest指的的目標域,必須設定multiValued為true。
FieldType
定義域的型別
<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
配置業務 Field
需求
對京東案例中的 products 表的資料進行索引,所以需要定義對應的 field 域。
分析配置
需要往索引庫新增的欄位有: 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"/>
複製程式碼
<!-- 目標域 -->
<field name="product_keywords" type="text_ik" indexed="true" stored="true" multiValued="true"/>
<!-- 將商品名稱新增到目標域 -->
<copyField source="product_name" dest="product_keywords"/>
<!-- 將商品描述新增到目標域 -->
<copyField source="product_description" dest="product_keywords"/>
複製程式碼
Dataimport
該外掛可以將資料庫中指定的sql語句的結果匯入到solr索引庫中。
-
第一步:新增 jar 包 Dataimport的jar包(solr-4.10.3\dist\solr-dataimporthandler-extras-4.10.3.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" />
-
第二步:配置 requesthandler 在 solrconfig.xml 中,新增一個 dataimport 的 requestHandler
<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
在 solrconfig.xml 同級目錄下,建立 data-config.xml
![](http://pbzzkhjh1.bkt.clouddn.com/1c648865-30cb-4dbe-9133-525692211bf4.jpg)
```xml
<dataConfig>
<dataSource
type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/taotao"
user="root"
password="root"/>
<document>
<entity name="products" query="select pid,name,catalog,catalog_name,price,description,picture from products ">
<field column="pid" name="id" />
<field column="name" name="product_name" />
<field column="catalog" name="product_catalog" />
<field column="catalog_name" name="product_catalog_name" />
<field column="price" name="product_price" />
<field column="description" name="product_description" />
<field column="picture" name="product_picture" />
</entity>
</document>
</dataConfig>
複製程式碼
- 第四步:重啟 tomcat
solrj 的使用
什麼是 solrj
solrj 就是 solr 伺服器的 java 客戶端
環境準備
jdk ide tomcat solrj
搭建工程
-
solrj 的依賴包和核心包
-
solrj 的擴充套件服務包
使用 solrj 完成索引維護
新增/修改索引
在solr中,索引庫中都會存在一個唯一鍵,如果一個Document的id存在,則執行修改操作,如果不存在,則執行新增操作。
@Test
public void insertAndUpdateIndex() throws Exception {
// 建立HttpSolrServer
HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
// 建立Document物件
SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", "c001");
doc.addField("name", "solr test111");
// 將Document物件新增到索引庫
server.add(doc);
// 提交
server.commit();
}
複製程式碼
刪除索引
根據指定 id 來刪除
根據條件來刪除
@Test
public void deleteIndex() throws Exception {
// 建立HttpSolrServer
HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
// 根據指定的ID刪除索引
// server.deleteById("c001");
// 根據條件刪除
server.deleteByQuery("id:c001");
// 刪除全部(慎用)
server.deleteByQuery("*:*");
// 提交
server.commit();
}
複製程式碼
查詢索引
簡單查詢
@Test
public void search01() throws Exception {
// 建立HttpSolrServer
HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
// 建立SolrQuery物件
SolrQuery query = new SolrQuery();
// 輸入查詢條件
query.setQuery("product_name:小黃人");
// 執行查詢並返回結果
QueryResponse response = server.query(query);
// 獲取匹配的所有結果
SolrDocumentList list = response.getResults();
// 匹配結果總數
long count = list.getNumFound();
System.out.println("匹配結果總數:" + count);
for (SolrDocument doc : list) {
System.out.println(doc.get("id"));
System.out.println(doc.get("product_name"));
System.out.println(doc.get("product_catalog"));
System.out.println(doc.get("product_price"));
System.out.println(doc.get("product_picture"));
System.out.println("=====================");
}
}
複製程式碼
複雜查詢
solr的查詢語法
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=+<desc|asc>[,+<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,設定格式字首和字尾。
程式碼
@Test
public void search02() throws Exception {
// 建立HttpSolrServer
HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
// 建立SolrQuery物件
SolrQuery query = new SolrQuery();
// 輸入查詢條件
query.setQuery("product_name:小黃人");
// query.set("q", "product_name:小黃人");
// 設定過濾條件
// 如果設定多個過濾條件的話,需要使用query.addFilterQuery(fq)
query.setFilterQueries("product_price:[1 TO 10]");
// 設定排序
query.setSort("product_price", ORDER.asc);
// 設定分頁資訊(使用預設的)
query.setStart(0);
query.setRows(10);
// 設定顯示的Field的域集合
query.setFields("id,product_name,product_catalog,product_price,product_picture");
// 設定預設域
query.set("df", "product_keywords");
// 設定高亮資訊
query.setHighlight(true);
query.addHighlightField("product_name");
query.setHighlightSimplePre("<em>");
query.setHighlightSimplePost("</em>");
// 執行查詢並返回結果
QueryResponse response = server.query(query);
// 獲取匹配的所有結果
SolrDocumentList list = response.getResults();
// 匹配結果總數
long count = list.getNumFound();
System.out.println("匹配結果總數:" + count);
// 獲取高亮顯示資訊
Map<String, Map<String, List<String>>> highlighting = response
.getHighlighting();
for (SolrDocument doc : list) {
System.out.println(doc.get("id"));
List<String> list2 = highlighting.get(doc.get("id")).get(
"product_name");
if (list2 != null)
System.out.println("高亮顯示的商品名稱:" + list2.get(0));
else {
System.out.println(doc.get("product_name"));
}
System.out.println(doc.get("product_catalog"));
System.out.println(doc.get("product_price"));
System.out.println(doc.get("product_picture"));
System.out.println("=====================");
}
}
複製程式碼