一、Solr概述
Solr 是Apache下的一個頂級開源項目,采用Java開發,它是基于Lucene的全文搜尋服務。Solr自帶伺服器功能,可以通過指令方式直接啟動solr服務。也可以把solr部署到Jetty、Tomcat等其他Servlet容器中運作。
- Solr與lucene的關系
Lucene是一個開放源代碼的全文檢索引擎工具包,它不是一個完整的全文檢索應用。Lucene僅提供了完整的查詢引擎和索引引擎,目的是為軟體開發人員提供一個簡單易用的工具包,以友善的在目标系統中實作全文檢索的功能,或者以Lucene為基礎建構全文檢索應用。Solr的目标是打造一款企業級的搜尋引擎系統,它是基于Lucene一個搜尋引擎服務,可以獨立運作,通過Solr可以非常快速的建構企業的搜尋引擎,通過Solr也可以高效的完成站内搜尋功能。
二、Solv安裝配置
2.1 下載下傳Solr
下載下傳位址:http://archive.apache.org/dist/lucene/solr/
如果是Windows版本,那麼下載下傳完成後直接解壓縮到指定目錄即可。目錄結果如下圖所示:
bin:solr的運作腳本;
contrib:solr相關的第三方擴充jar包;
dist:該目錄包含build過程中産生的war和jar檔案,以及相關的依賴檔案;
docs:api文檔;
example:solr工程的示例;
licenses:各種許可和協定;
server:solr自帶的伺服器目錄。其中有兩個比較重要的目錄:
|- solr:運作Solr的配置檔案都儲存在這裡。其中,它包含一個子檔案夾configsets,該檔案夾存放了solr的示例配置檔案
|- solr-webapp:solr背景管理系統所在目錄
2.2 啟動自帶solr服務
第一步:在指令行進入solr/bin目錄,然後執行solr start指令即可。
solr服務預設監聽8983端口。啟動成功後,在浏覽器上輸入localhost:8983/solr即可打開solr管理界面。
2.3 建立solr core
一個solr core就是一個索引庫。一個solr伺服器上可以有多個solr core。
第一步:進入%solr_home%/server/solr目錄,建立一個目錄,該目錄作為一個索引庫目錄存放我們建立的索引。
第二步:将%solr_home%\server\solr\configsets\sample_techproducts_configs目錄下的conf檔案夾拷貝到solrtest目錄中。
第三步:重新開機solr服務。
solr restart -p 8983
例如:
啟動成功後,重新通路solr管理界面。
第四步:點選左邊Core Admin菜單,然後點選Add Core,在name和InstanceDir輸入框中輸入solr core檔案夾的名稱,輸入完後點選藍色的Add Core按鈕。
這時候在左邊core selector中可以看到我們建立的solr core。
2.4 管理界面介紹
(1)DashBoard
儀表盤,顯示了該Solr執行個體開始啟動運作的時間、版本、系統資源、jvm等資訊。
(2)Logging
Solr運作日志資訊。
(3)Core Admin
Solr Core管理界面,在這裡可以添加SolrCore執行個體。
(4)Java Properties
Solr在JVM 運作環境中的屬性資訊,包括類路徑、檔案編碼、jvm記憶體設定等資訊。
(5)Thread Dump
顯示Solr Server中目前活躍線程資訊,同時也可以跟蹤線程運作棧資訊。
(6)Core Selector
選擇一個SolrCore進行詳細操作。具體操作如下所示:
其中有幾個比較常用的功能:
Analysis:通過此界面可以測試索引分析器和搜尋分析器的執行情況。
Dataimport:定義資料導入處理器,可以從關系資料庫将資料導入到Solr索引庫中。預設沒有配置,需要手工配置;
Documents:通過/update表示更新索引,solr預設根據id(唯一限制)域來更新Document的内容,如果根據id值搜尋不到id域則會執行添加操作,如果找到則更新;
Query:通過/select執行搜尋索引,必須指定“q”查詢條件方可搜尋。
q: 查詢關鍵字;
fq: (filter query)過濾查詢,在q查詢結果中再把符合fq的内容篩選出來;
sort:排序,desc代表降序,asc代表升序;
start: 分頁顯示使用,開始記錄下标,從0開始;
rows:指定傳回結果最多有多少條記錄,配合start來實作分頁;
fl: (Field List)指定傳回那些字段内容,用逗号或空格分隔多個;
df:(Default Field)指定預設搜尋Field;
wt: (writer type)指定輸出格式,可以有xml、json等格式;
hl: 是否高亮 ,設定高亮Field,設定格式字首和字尾;
三、Solrj的使用
3.1 什麼是solrj
solrj是通路Solr服務的java用戶端,提供索引和搜尋的請求方法。
3.2 環境搭建
搭建Maven工程,并引入solrj相關坐标;
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>8.2.0</version>
</dependency>
3.3 添加或修改索引
public class CreateIndexTest {
// 設定solr服務接口
String baseURL = "http://127.0.0.1:8983/solr/solrtest";
SolrClient solrClient;
@Before
public void init() {
// 建立SolrServer對象
solrClient = new HttpSolrClient.Builder(baseURL).build();
}
// 添加和更新索引
@Test
public void testCreateIndex() throws Exception {
// 建立SolrInputDocument對象
SolrInputDocument document = new SolrInputDocument();
// 添加Field
document.addField("id", "103");
document.addField("content_ik", "中華人民共和國");
// 把SolrInputDocument對象添加到索引庫中
solrClient.add(document);
// 送出
solrClient.commit();
}
}
上面solrClient.add(document)方法會根據id域來更新Document的内容,如果根據id值搜尋不到id域則會執行添加操作。
3.4 删除索引
// 根據條件删除
solrClient.deleteByQuery("*:*");
// 送出
solrClient.commit();
*注意:*:代表删除所有索引,需要慎用。
3.5 查詢索引
@Test
public void testSearchIndex() throws Exception {
// 建立搜尋對象
SolrQuery query = new SolrQuery();
// 設定搜尋條件
query.setQuery("*:*");
// 發起搜尋請求
QueryResponse response = solrClient.query(query);
// 處理搜尋結果
SolrDocumentList results = response.getResults();
System.out.println("搜尋到的結果總數:" + results.getNumFound());
// 周遊搜尋結果
for (SolrDocument solrDocument : results) {
System.out.println("----------------------------------------------------");
System.out.println("id:" + solrDocument.get("id"));
System.out.println("content" + solrDocument.get("content"));
}
}
3.6 複雜查詢
@Test
public void testSearchIndex2() throws Exception {
// 建立搜尋對象
SolrQuery solrQuery = new SolrQuery();
// 設定查詢條件
solrQuery.setQuery("搜尋引擎");
// 設定過濾條件
solrQuery.setFilterQueries("bookName:lucene", "bookPrice:[49 TO 99]");
// 設定排序
solrQuery.setSort("bookPrice", ORDER.desc);
// 設定分頁
solrQuery.setStart(0);
solrQuery.setRows(10);
// 設定顯示Field域
solrQuery.setFields("id, bookName, bookPrice, bookPic, bookRemark");
// 設定預設搜尋Field域
solrQuery.set("df", "bookName");
// 設定高亮
solrQuery.setHighlight(true);
solrQuery.addHighlightField("bookName");
solrQuery.setHighlightSimplePre("<font color=\"red\">");
solrQuery.setHighlightSimplePost("</font>");
// 查詢資料
QueryResponse response = solrClient.query(solrQuery);
// 擷取查詢結果的記錄數
SolrDocumentList results = response.getResults();
System.out.println("搜尋到的資料總條數:" + results.getNumFound());
Map<String, Map<String, List<String>>> map = response.getHighlighting();
// 解析查詢結果
for (SolrDocument solrDocument : results) {
System.out.println("----------------------------------------------------");
// 顯示高亮
List<String> list = map.get(solrDocument.get("id")).get("bookName");
System.out.println("編号:" + solrDocument.get("id"));
if (list != null && list.size() > 0) {
System.out.println("書名:" + list.get(0));
} else {
System.out.println("書名:" + solrDocument.get("bookName"));
}
System.out.println("價格:" + solrDocument.get("bookPrice"));
System.out.println("圖檔:" + solrDocument.get("bookPic"));
System.out.println("描述:" + solrDocument.get("bookRemark"));
}
}
四、配置中文分詞器
第一步:下載下傳ikanalyzer。
下載下傳位址:https://mvnrepository.com/artifact/com.jianggujin/IKAnalyzer-lucene/8.0.0
第二步:把下載下傳好的jar包複制到%solr_home%\server\solr-webapp\webapp\WEB-INF\lib目錄下。
第三步:把下面三個檔案複制到%solr_home%\server\solr-webapp\webapp\WEB-INF\classes目錄下。這三個檔案可以從ikanalyzer.jar檔案中獲得。
第四步:修改%solr_home%\server\solr\solrtest\conf\managed-schema檔案,配置中文分詞器。
<!-- ik分詞器 -->
<fieldType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
<field name="content_ik" type="text_ik" indexed="true" stored="true" />
修改完成後重新開機solr服務,進入analysis頁面,在Field Value中輸入要分詞的内容,然後再選擇FieldType為content_ik,最後點選藍色按鈕即可。效果如下圖所示:
下面沒有使用ikanalyzer分詞器的效果(供大家參考):
五、導入資料
需求:使用solr背景導入資料庫中book表的資料到solr中。
功能分析:
1.需要在solr的schema.xml檔案定義要存儲的商品Field。
2.需要把MySQL的資料導入到solr索引庫中
3.開發搜尋功能
5.1 引入jar包
複制%solr_home%/dist目錄下的solr-dataimporthandler包到%solr_home%/contrib/dataimporthandler/lib目錄下。
準備mysql驅動包,然後添加到%solr_home%\contrib\db\lib目錄下。如果沒有lib目錄,則自己建立。
修改%solr_home%\server\solr\solrtest\conf目錄下的sqlrconfig.xml檔案。修改内容如下:
<lib dir="${solr.install.dir:../..}/contrib/dataimporthandler/lib" regex=".*\.jar" />
<lib dir="${solr.install.dir:../..}/contrib/db/lib" regex=".*\.jar" />
5.2 配置資料源
在%solr_home%\server\solr\solrtest\conf目錄下建立data-config.xml檔案,該檔案配置了Document中每個Field與資料庫表的對應關系。配置如下:
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
<!-- 資料庫資訊 -->
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/solr"
user="root" password="root"/>
<document>
<!-- document實體 -->
<entity name="book" query="SELECT * FROM book">
<!-- 資料庫字段映射solr字段 -->
<field column="id" name="id"/>
<field column="name" name="bookName"/>
<field column="price" name="bookPrice"/>
<field column="pic" name="bookPic"/>
<field column="remark" name="bookRemark"/>
</entity>
</document>
</dataConfig>
修改%solr_home%\server\solr\solrtest\conf目錄下的sqlrconfig.xml檔案:
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>
5.3 配置Field
修改%solr_home%\server\solr\solrtest\conf目錄下的managed-schema檔案,在最後面加入下面内容:
<field name="bookName" type="text_ik" indexed="true" stored="true" />
<field name="bookPrice" type="pint" indexed="true" stored="true" />
<field name="bookPic" type="string" indexed="false" stored="true" />
<field name="bookRemark" type="text_ik" indexed="true" stored="false" />
<field name="book_keywords" type="text_ik" indexed="true" stored="true" multiValued="true"/>
<copyField source="bookName" dest="book_keywords"/>
<copyField source="bookRemark" dest="book_keywords"/>
copyField:将多個Field複制到一個Field中,以便進行統一的檢索。當建立索引時,solr伺服器會自動的将source域的内容複制到dest目标域中。如果指定dest目标域為預設搜尋域,可以提高查詢效率。
配置完成後,重新開機solr服務。
5.4 背景導入操作
點選Dataimport菜單,選擇Entity,然後點選Execute按鈕執行導入。導入成功後界面如下所示:
在Overview中可以看到索引庫的資訊。
六、SpringBoot整合solr
第一步:建立springboot項目,引入相關坐标。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
第二步:建立實體類。
package solrjtest.beans;
import lombok.Data;
@Data
public class Book {
private Integer id;
private String name;
private Integer price;
private String pic;
private String remark;
}
第三步:建立Service接口,該接口定義一個方法,用于從solr中查詢索引,并傳回結果。
public interface IBookService {
List<Book> searchBook() throws Exception;
}
第四步:建立Service實作類。
package solrjtest.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import solrjtest.beans.Book;
import solrjtest.service.IBookService;
@Service
public class BookServiceImpl implements IBookService {
@Autowired
private SolrClient solrClient;
@Override
public List<Book> searchBook() throws Exception {
// 建立搜尋對象
SolrQuery solrQuery = new SolrQuery();
// 設定查詢條件
solrQuery.setQuery("搜尋引擎");
// 設定過濾條件
solrQuery.setFilterQueries("bookName:lucene", "bookPrice:[49 TO 99]");
// 設定排序
solrQuery.setSort("bookPrice", ORDER.desc);
// 設定分頁
solrQuery.setStart(0);
solrQuery.setRows(10);
// 設定顯示Field域
solrQuery.setFields("id, bookName, bookPrice, bookPic, bookRemark");
// 設定預設搜尋Field域
solrQuery.set("df", "bookName");
// 設定高亮
solrQuery.setHighlight(true);
solrQuery.addHighlightField("bookName");
solrQuery.setHighlightSimplePre("<font color=\"red\">");
solrQuery.setHighlightSimplePost("</font>");
// 查詢資料
QueryResponse response = solrClient.query(solrQuery);
// 擷取查詢結果的記錄數
SolrDocumentList results = response.getResults();
System.out.println("搜尋到的資料總條數:" + results.getNumFound());
Map<String, Map<String, List<String>>> map = response.getHighlighting();
List<Book> books = new ArrayList<Book>();
// 解析查詢結果
for (SolrDocument solrDocument : results) {
// 顯示高亮
List<String> list = map.get(solrDocument.get("id")).get("bookName");
// 擷取Field的值
String id = (String) solrDocument.get("id");
String bookName = "";
if (list != null && list.size() > 0) {
bookName = list.get(0);
} else {
bookName = (String) solrDocument.get("bookName");
}
int bookPrice = (int) solrDocument.get("bookPrice");
String bookPic = (String) solrDocument.get("bookPic");
String bookRemark = (String) solrDocument.get("bookRemark");
// 把擷取到Field的值封裝成Book對象
Book book = new Book();
book.setId(Integer.parseInt(id));
book.setName(bookName);
book.setPrice(bookPrice);
book.setPic(bookPic);
book.setRemark(bookRemark);
books.add(book);
}
return books;
}
}
第五步:建立控制器。
@Controller
@RequestMapping("/book")
public class BookController {
@Autowired
private IBookService bookService;
@RequestMapping(path="/list", produces={"application/json;charset=utf-8"})
@ResponseBody
public List<Book> list() {
try {
return bookService.searchBook();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
第六步:配置solr。
spring:
data:
solr:
host: http://192.168.31.20:8983/solr/solrtest
第七步:建立啟動類。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
最終在浏覽器上看到的效果如下圖所示: