1 Solr介紹
1.1 什么是solr?
Solr
是一個獨立的企業級搜索應用服務器,它對外提供類似於Web-service的API接口。用戶可以通過http請求,向搜索引擎服務器提交一定格式的XML文件,生成索引;也可以通過Http Get操作提出查找請求,並得到XML格式的返回結果。
Solr
是apache
的頂級開源項目,它是使用java開發 ,基於lucene
的全文檢索服務器。
Solr
比lucene
提供了更多的查詢語句,而且它可擴展、可配置,同時它對lucene
的性能進行了優化。
Solr
是如何實現全文檢索的呢?
1,索引流程:solr客戶端(瀏覽器、java程序)可以向solr服務端發送POST請求,請求內容是包含Field等信息的一個xml文檔,通過該文檔,solr實現對索引的維護(增刪改)
2,搜索流程:solr客戶端(瀏覽器、java程序)可以向solr服務端發送GET請求,solr服務器返回一個xml/json文檔。
1.2 Solr和lucene的區別
Lucene
是一個全文檢索引擎工具包,它只是一個jar包,不能獨立運行,對外提供服務。
Solr
是一個全文檢索服務器,它可以單獨運行在servlet
容器,可以單獨對外提供搜索和索引功能。Solr
比lucene
在開發全文檢索功能時,更快捷、更方便。
2 Solr安裝配置
2.1 下載solr
Solr
和lucene
的版本是同步更新的,最新的版本是8.1.0/
本課程使用的版本:7.1.0
下載地址:https://mirrors.tuna.tsinghua.edu.cn/apache/lucene/solr/
下載版本:7.1.0
- src.tgz:帶src表示是帶源碼文件的壓縮包,無src是已經編譯過的壓縮包
- .tgz:Linux相關操作系統使用的壓縮包
- .zip:Windows操作系統使用的壓縮包
Jetty
是一個開源的servlet容器,它為基於Java
的web
容器,例如JSP
和servlet
提供運行環境。Jetty是使用Java
語言編寫的,它的API以一組JAR包的形式發布。開發人員可以將Jetty
容器實例化成一個對象,可以迅速為一些獨立運行(stand-alone)
的Java
應用提供網絡和web連接。
2.2 啟動Solr
solr的啟動、停止、查看命令:
- 啟動:bin\solr.cmd start
- 停止:bin\solr stop 或bin\solr stop -all
- 查看:bin\solr status
訪問地址:http://localhost:8983/solr/#/
2.3 Tomcat安裝運行環境
Jdk:1.8及以上
Solr:7.1
Web服務器:tomcat 8(改端口9080)
2.3.1 操作步驟
1、找到如下目錄內容:
D:\guoweixin\solr\solr-7.1.0\server\solr-webapp
2、復制到Tomcat下,並命令為solr
D:\guoweixin\solr\apache-tomcat-solr\webapps
2、將solr-7.1.0\server\lib\ext下的所有jar包,以及solr-7.1.0\server\lib下以metrics開頭的jar、gmetric4j-1.0.7.jar復制到apache-tomcat-8\webapps\solr\WEB-INF\lib下
3、在tomcat\webapps\solr\WEB-INF中,新建classes文件夾,將solr-7.1.0\server\resources下的log4j.properties文件拷貝到里面
創建Solr CoreAdmin管理(Solr Home)
4、創建SOLR HOME目錄(solr_home)
5、拷貝solr-7.1.0\server\solr下所有文件、文件夾復制到solr_home目錄下
6、拷貝solr-7.1.0 下contrib和dist文件夾至solr_home目錄下
7、在solr_home目錄下新建demo_core文件夾;
並拷貝D:\guoweixin\solr\solr_home\configsets\sample_techproducts_configs目錄下conf文件夾至solr_home\demo_core下
8(需要)、修改solr_home\demo_core\conf\solrconfig.xml文件,如下(75行處)
9、修改tomcat\webapps\solr\WEB-INF中的web.xml文件
新增如下部分,默認是注釋掉的。 (40行處)
其中env-entry-value值為solr_home對應值,即solr home目錄
10、修改tomcat\webapps\solr\WEB-INF中的web.xml文件(注釋如下部分內容)最下面162行
11、啟動Tomcat
啟動tomcat,訪問http://localhost:8080/solr/index.html
2.4 solr界面介紹
啟動solr服務
http://localhost:8080/solr/index.html
2.4.1 Dashboard
儀表盤,顯示了該Solr
實例開始啟動運行的時間、版本、系統資源、jvm等信息。
2.4.2 Logging
顯示solr運行出現的異常或錯誤
2.4.3 Core Admin
Solr Core
的管理界面。在這里可以添加SolrCore
實例。
主要有Add Core
(添加核心), Unload
(卸載核心),Rename
(重命名核心),Reload
(重新加載核心),Optimize
(優化索引庫)
Add Core
是添加core
:主要是在instanceDir
對應的文件夾里生成一個core.properties
文件 。
name:給core起的名字;
instanceDir:與我們在配置solr到tomcat里時的solr_home里新建的core文件夾名一致;
dataDir:確認Add Core時,會在new_core目錄下生成名為data的文件夾
config:new_core下的conf下的config配置文件(solrconfig.xml)
schema: new_core下的conf下的schema文件(schema.xml)
2.4.4 java properties
Solr在JVM 運行環境中的屬性信息,包括類路徑、文件編碼、jvm內存設置等信息。可查看到java相關的一些屬性的信息。
2.4.5 Tread Dump
顯示Solr Server
中當前活躍線程信息,同時也可以跟蹤線程運行棧信息。
2.4.6 Core selector(重點)
需要在Core Admin
里添加了core
后才有可選項。
選擇一個SolrCore
進行詳細操作,如下:
2.4.6.1 Analysis(重點)
通過此界面可以測試索引分析器和搜索分析器的執行情況。
注:solr中,分析器是綁定在域的類型中的。
2.4.6.2 dataimport
可以定義數據導入處理器,從關系數據庫將數據導入到Solr索引庫中。
默認沒有配置,需要手工配置。
2.4.6.3 Document
通過/update
表示更新索引,solr默認根據id(唯一約束)域來更新Document的內容,如果根據id值搜索不到id域則會執行添加操作,如果找到則更新。
通過此菜單可以創建索引、更新索引、刪除索引等操作。
2.4.6.4 Query(重點)
通過/select
執行搜索索引,必須指定“q”查詢條件方可搜索。
2.5 Solr core的配置(創建)
1、新建core(創建guo_core文件夾)
新建的solrhome文件的位置為:D:\guoweixin\solr\solr_home\guo_core
2、D:\guoweixin\solr\solr_home\configsets\sample_techproducts_configs\ 目錄下conf文件夾復制到solr_home\guo_core下
3、在http://localhost:8080/solr/index.html管理界面中添加guo_core
點擊 add Core 按鈕進行添加
3 Solr導入數據
3.1 查看core
通過此查看創建的guo_core,則說明沒有相關配置文件,需要添加並修改。
3.2 DataImport導入數據
該功能是將數據庫中數據通過Sql語句方式導入到Solr索引庫中。
3.2.1 第一步:添加jar包
D:\guoweixin\solr\solr-7.1.0\dist 下的jar
mysql jar
配置Solr:找到自帶的中文分詞器
D:\guoweixin\solr\solr-7.1.0\contrib\analysis-extras\lucene-libs
以上所有jar全部復制到 webapps/solr/WEB-INF/lib下
3.2.2 第二步:配置中文分詞器
修改同目錄下的managed-schema
文件
1、在文件最后方插入中文分詞器:
<!-- ChineseAnalyzer -->
<fieldType name="solr_cnAnalyzer" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="org.apache.lucene.analysis.cn.smart.HMMChineseTokenizerFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.apache.lucene.analysis.cn.smart.HMMChineseTokenizerFactory"/>
</analyzer>
</fieldType>
3.2.3 managed-schema文件詳解
找到solr_home\core_meeting\conf下managed-schema文件
在managed-schema.xml文件中,主要配置SolrCoe數據信息,包括:Field和FieldType的定義等信息,在solr中,Field和FieldType都需要先定義后使用!
Field詳解:
學習詳細參考:http://blog.csdn.net/mine_song/article/details/58065323
https://www.cnblogs.com/gslblog/p/6582008.html
name:指定域的名稱(自定義) type:指定域的類型 indexed:是否索引 是:(將分好的詞進行索引,索引的目的,就是為了搜索)
否:不索引,也就是不對該field域進行搜索。 stored:是否存儲
是:將field域中的內容存儲到文檔域中。存儲的目的,就是為了搜索頁面顯示取值用的
否:不將field域中的內容存儲到文檔域中。不存儲,則搜索頁面中沒法獲取該field域的值。 required:是否必須
multiValued:是否多值,比如查詢數據需要關聯多個字段數據,一個Field存儲多個值信息,必須將multiValued設置為true。
dynamicField詳解(199行):
name
為*_i,定義它的type
為int,那么在使用這個字段的時候,任何以_i
結果的字段都被認為符合這個定義。
uniqueKey
其中的id是在Field
標簽中已經定義好的域名,而且該域設置為required
為true
。
一個managed-schema
文件中必須有且僅有一個唯一鍵
copyField
復制域
應用場景:我們在搜索時比如輸入java
,一篇文章分為標題、簡介、內容等很多字段,輸入的關鍵字需要制定solr
中的域進行檢索,不可能從一個表中將所有字段進行索引,因為有些字段不需要索引,所以出現copyField
域,把多個域的關鍵詞復制到同一個域,多個域時,可以放到一個域中。就不用定義那么多域了。搜索比較方便
實例:<copyField source="projectName" dest="keywords"/>
Source
:是Field
域的名稱
Dest
:是destination
的縮寫 目標域
使用案例:
1、 兩個普通域 :title
和author
2、 使用復制域,將兩個域進行索引檢索
3、 該域名field name=”text”
即是復制域
fieldType
域類型:
分詞器:
- Name:指定域類型的名稱
- Class:指定該域類型對應的solr的類型
- Analyzer:指定分析器
- Type:index、query,分別指定搜索和索引時的分析器
- Tokenizer:指定分詞器
- Filter:指定過濾器
3.2.4 第三步:修改 solrconfig.xml文件
找到D:\guoweixin\solr\solr_home\guo_core\conf文件夾下的solrconfig.xml,添加dataimport
首先查詢是否存在dataimport
的equestHandler
,如果不存在,因此需要手動添加。為了以后便於維護此文件,我們就在requestHandler
起始位置,約為720行處,添加如下內容
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>
3.2.5 第四步:創建data-config.xml
data-config.xml作用:數據庫連接相關信息、SQL以及查詢結果映射對應域中
在solrconfig.xml同級目錄下,創建data-config.xml
- Query代表:查詢的SQL語句
- Column代表:SQL查詢的列名
- Name代表:Solr 域Filed中的域名
<?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>
<entity name="products" query="select pid,pname,catalog_name,price,description,picture from products ">
<field column="pid" name="id"/>
<field column="pname" name="prod_pname"/>
<field column="catalog_name" name="prod_catalog_name"/>
<field column="price" name="prod_price"/>
<field column="description" name="prod_description"/>
<field column="picture" name="prod_picture"/>
</entity>
</document>
</dataConfig>
3.2.6 第四步:定義域
修改同目錄下的managed-schema
文件
1、在文件最后方插入中文分詞器:
同時還要配置其Field
域:來配置字段【這里的名字要與data-config
中的域名一模一樣】
<field name="prod_pname" type="solr_cnAnalyzer" indexed="true" stored="true" required="true" />
<field name="prod_catalog_name" type="string" indexed="true" stored="true" required="true" />
<field name="prod_price" type="pdouble" indexed="true" stored="true" required="true" />
<field name="prod_description" type="solr_cnAnalyzer" indexed="true" stored="true" required="true" />
<field name="prod_picture" type="string" indexed="false" stored="true" required="true" />
其中prod_pname
需要模糊查詢(中文分詞),故將其類型改為solr_cnAnalyzer
3.2.7 第五步:啟動服務
1、啟動Tomcat
服務器
2、查看數據導入結果
重啟Tomcat
服務器,進入 guo_core
,測試中文分詞器效果
重啟Tomcat
服務器,進入guo_core
中 DataImport
執行 execute
查詢描述
1,q 查詢的關鍵字,此參數最為重要,例如,q=id:1,默認為q=:,
2,fl 指定返回(回顯)哪些字段,用逗號或空格分隔,注意:字段區分大小寫,例如,fl= id,title,sort
3,start 返回結果的第幾條記錄開始,一般分頁用,默認0開始
4,rows 指定返回結果最多有多少條記錄,默認值為 10,配合start實現分頁
5,sort 排序方式,例如id desc 表示按照 “id” 降序
6,wt (writer type)指定輸出格式,有 xml, json等
7,fq (filter query)過慮查詢,提供一個可選的篩選器查詢。返回在q查詢符合結果中同時符合的fq條件的查詢結果,例如:q=id:1&fq=sort:[1 TO 5],找關鍵字id為1 的,並且sort是1到5之間的。
8,df 默認的查詢字段,一般默認指定。
9,h1 是否高亮,
3.3 客戶端查詢語法
- q查詢關鍵字,查詢所有使用:。
請求的q是字符串
多個條件可以:之間用AND
或OR
關聯
fq
(filter query)過濾查詢,作用:在q
查詢符合結果中同時是fq
查詢符合的,例如:
請求fq
是一個數組(多個值)
過濾查詢價格從1到1的記錄。
也可以在“q”查詢條件中使用product_price:[1 TO 20]
,如下:
也可以使用“*”表示無限,例如:
10以上
10以下
sort
排序,格式:sort=<field name>+<desc|asc>[,<field name>+<desc|asc>]….
示例:
start
- 分頁顯示使用,開始記錄下標,從0開始
5.rows
- 指定返回結果最多有多少條記錄,配合start
來實現分頁。
實際開發時,知道當前頁碼和每頁顯示的個數最后求出開始下標。fl
- 指定返回那些字段內容,用逗號或空格分隔多個(回顯)
df
-指定一個搜索默認Field
wt
- (writer type)指定輸出格式
9.hl
是否高亮 ,設置高亮Field
,設置格式前綴和后綴。
hl.fl
指定高亮域的名稱
4 springboot集成solr
配置solr
的maven
坐標
4.1 springboot整合solr的maven配置如下
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
4.2 在application.yml配置文件中配置solr的Host地址
spring:
data:
solr:
host: http://localhost:8081/solr/demo_core
4.3 准備實體類
這個實體類就是solr服務器的配置文件配置的字段。@Field
注解是映射作用,Java
實體類與solr
索引的映射。
@Data
public class Products {
@Field("id")
private String pid;
@Field("prod_pname")
private String pname;
@Field("prod_catalog_name")
private String catalogName;
@Field("prod_price")
private Double price;
@Field("prod_description")
private String description;
@Field("prod_picture")
private String picture;
}
4.4 注入SolrClient對象
用法示例如下
@Autowired
SolrClient solrClient;
4.4.1 springboot添加solr索引庫(給solr數據庫添加數據)
public void addData() throws Exception{
Products products=new Products();
products.setPid("557");
products.setPname("可愛的胖");
products.setCatalogName("京東");
products.setPrice(80.90);
products.setDescription("很乖的寵物");
products.setPicture("test.jpg");
UpdateResponse updateResponse = solrClient.addBean(products);
solrClient.commit();
System.out.println("添加成功");
}
4.4.2 springboot修改和上述的添加一樣,有就修改,沒有就添加
4.4.3 springboot刪除solr索引庫
public void delData() throws Exception{
solrClient.deleteById("890");
solrClient.commit();
// solrClient.deleteByQuery("*:*");//先查詢然后刪除,*:* 這里查詢條件是全部,因此執行之后會清空索引庫
System.out.println("刪除成功");
}
4.4.4 springboot查詢solr索引庫的數據
public void select() throws Exception{
SolrQuery solrQuery=new SolrQuery("*:*");//查詢所有
QueryResponse query = solrClient.query(solrQuery);
long numFound = query.getResults().getNumFound();
System.out.println("總記錄數:"+numFound);
List<Products> beans = query.getBeans(Products.class);
for(Products product:beans){
System.out.println(product.getPid()+" "+product.getPname()+" "+product.getDescription());
}
}
4.4.5 模仿京東條件篩選搜索
public void moreSelect() throws Exception{
SolrQuery solrQuery=new SolrQuery();
//q
solrQuery.set("q","prod_pname:衣服");
//fq:過濾查詢
solrQuery.setFilterQueries("prod_catalog_name:京東");
// 多條件過濾
// solrQuery.setFilterQueries("prod_catalog_name:京東 or prod_catalog_name:淘寶");
//價格過濾
// solrQuery.addFilterQuery("prod_price:[10 TO *]");
//排序sort
// solrQuery.addSort("prod_price",SolrQuery.ORDER.asc);
//分頁(規則和limit一樣)
solrQuery.setStart(0);
solrQuery.setRows(5);
//回顯(想查出來哪幾個字段)
// solrQuery.setFields("prod_name","pid");
//高亮配置
solrQuery.setHighlight(true);//啟動高亮
solrQuery.addHighlightField("prod_pname");//設置域名稱
solrQuery.setHighlightSimplePre("<font color='red'>");
solrQuery.setHighlightSimplePost("</font>");
QueryResponse query = solrClient.query(solrQuery);
//得到高亮數據
Map<String, Map<String, List<String>>> highlighting = query.getHighlighting();
long numFound = query.getResults().getNumFound();
System.out.println("總記錄數:"+numFound);
List<Products> beans = query.getBeans(Products.class);
for(Products product:beans){
Map<String, List<String>> stringListMap = highlighting.get(product.getPid());
List<String> prod_pname = stringListMap.get("prod_pname");
String pname = prod_pname.get(0);
product.setPname(pname);//把名稱重新賦值為高亮樣式的名稱
System.out.println(product.getPid()+" "+product.getPname()+" "+product.getCatalogName());
}
}