一、ES分詞器
1、默認分詞器
ES文檔的數(shù)據(jù)拆分成一個個有完整含義的關鍵詞,并將關鍵詞與文檔對應,這樣就可以通過關鍵詞查詢文檔。要想正確的分詞,需要選擇合適的分詞器。
standard analyzer:Elasticsearch的默認分詞器,根據(jù)空格和標點符號對應英文進行分詞,會進行單詞的大小寫轉換。
默認分詞器是英文分詞器,對中文是一字一詞。
-
測試默認分詞器的效果
GET /_analyze { "text":"z z x", "analyzer": "standard" }
2、IK分詞器
2.1 IK分詞器安裝及測試
IK分詞器提供了兩種算法:
1)ik_smart:最少切分
2)ik_max_word:最細粒度劃分
-
關閉docker容器中的ES服務和kibana:
docker stop elasticsearch
,docker stop kibana
-
下載IKAnalyzer:
https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v8.6.1/elasticsearch-analysis-ik-8.6.1.zip
-
通過mobax上傳至虛擬機的目錄/,然后進行解壓縮:
unzip elasticsearch-analysis-ik-8.6.1.zip -d /usr/local/elasticsearch/plugins/analysis-ik
-
切換至es用戶:
su es
-
進入bin目錄:
cd /usr/local/elasticsearch/bin
-
啟動ES服務并在后臺運行:
./elasticsearch -d
-
切換到kibana的bin目錄:
cd ../../kibana-8.6.1/bin/
-
啟動kibana:
./kibana
-
測試IK分詞器ik_smart(最少切分)
GET /_analyze { "text":"我是要成為海賊王的男人", "analyzer": "ik_smart" }
即一段話中的字只會被劃分一次
-
測試IK分詞器ik_max_word(最細粒度劃分)
GET /_analyze { "text":"我是要成為海賊王的男人", "analyzer": "ik_max_word" }
即一段話中的字可能會被劃分多次
2.2 IK分詞器詞典
IK分詞器根據(jù)詞典進行分詞,詞典文件在IK分詞器的config目錄中。
main.dic:IK中內置的詞典。記錄了IK統(tǒng)計的所有中文單詞。
IKAnalyzer.cfg.xml:用于配置自定義詞庫。
-
進入到IK分詞器的配置目錄:
cd /usr/local/elasticsearch/plugins/analysis-ik/config
-
切換root用戶進行修改:
su root
-
修改配置文件:
vim IKAnalyzer.cfg.xml
,修改如下:<entry key="ext_dict">ext_dict.dic</entry> <entry key="ext_stopwords">ext_stopwords.dic</entry>
-
創(chuàng)建并編輯擴展詞:
vim ext_dict.dic
,添加如下:率土之濱
此時率土之濱會被分成一個詞。
-
創(chuàng)建并編輯停用詞:
vim ext_stopwords.dic
,添加如下率土
此時率土不會被分成一個詞。
-
切換到es用戶:
su es
-
重啟ES服務
1)找到對應的進程id:ps -ef |grep elastic
2)根據(jù)id殺死該進程:kill -9 ID號
3)進入到elasticsearch的bin目錄:cd /usr/local/elasticsearch/bin
4)啟動ES服務:./elasticsearch -d
-
重啟kibana服務
1)找到對應的進程id:netstat -anp | grep 5601
2)根據(jù)id殺死該進程:kill -9 ID號
3)進入到kibana的bin目錄:cd ../../kibana-8.6.1/bin/
4)重啟kibana服務:./kibana
3、拼音分詞器
-
下載拼音分詞器:
https://github.com/medcl/elasticsearch-analysis-pinyin/releases/download/v8.6.1/elasticsearch-analysis-pinyin-8.6.1.zip
-
通過mobax上傳到虛擬機的/目錄,解壓到elasticsearch的plugins/analysis-pinyin目錄下:
unzip elasticsearch-analysis-pinyin-8.6.1.zip -d /usr/local/elasticsearch/plugins/analysis-pinyin
-
切換到es用戶:
su es
-
重啟ES服務
1)找到對應的進程id:ps -ef |grep elastic
2)根據(jù)id殺死該進程:kill -9 ID號
3)進入到elasticsearch的bin目錄:cd /usr/local/elasticsearch/bin
4)啟動ES服務:./elasticsearch -d
-
重啟kibana服務
1)找到對應的進程id:netstat -anp | grep 5601
2)根據(jù)id殺死該進程:kill -9 ID號
3)進入到kibana的bin目錄:cd ../../kibana-8.6.1/bin/
4)重啟kibana服務:./kibana
-
測試拼音分詞器
GET /_analyze { "text":"我是要成為海賊王的男人", "analyzer": "pinyin" }
4、自定義分詞器
需要對一段內容既進行文字分詞,又進行拼音分詞,此時需要自定義ik+pinyin分詞器。
-
在創(chuàng)建索引時設置自定義分詞器
PUT student3 { "settings": { "analysis": { "analyzer": { "ik_pinyin":{//自定義分詞器名 "tokenizer":"ik_max_word",//基本分詞器 "filter":"pinyin_filter"//配置過濾分詞器 } }, "filter": { "pinyin_filter":{ "type":"pinyin",//另一個分詞器 "keep_separete_first_letter":false,//是否分詞每個字的首字母 "keep_full_pinyin":true,//是否全拼分詞 "keep_original":true,//是否保留原始輸入 "remove_duplicated_term":true//是否刪除重復項 } } } }, "mappings": { "properties": { "age":{ "type": "integer" }, "name":{ "type": "text", "store": true, "index": true, "analyzer": "ik_pinyin" } } } }
即在ik分詞器分詞后,再用拼音分詞器進行分詞。
-
測試自定義分詞器ik+pinyin
GET /student3/_analyze { "text":"我是要成為海賊王的男人", "analyzer": "ik_pinyin" }
“keep_separete_first_letter”:false,所以沒有wsycwhzwdnr這一段首字母拼音。
“keep_full_pinyin”:true,所以每個字的全拼都會被分詞。
“keep_original”:true,所以ik分詞器分詞后的結果也還在。
“remove_duplicated_term”:true,所以分詞器分詞后顯示的結果不會重復。
二、搜索文檔
1、添加文檔數(shù)據(jù)
-
創(chuàng)建students索引
PUT /students { "mappings": { "properties": { "id": { "type": "integer", "index": true }, "name": { "type": "text", "store": true, "index": true, "analyzer": "ik_smart" }, "info": { "type": "text", "store": true, "index": true, "analyzer": "ik_smart" } } } }
-
在students索引中創(chuàng)建文檔
POST /students/_doc { "id":1, "name":"羚羊王子", "info":"阿里嘎多美羊羊桑" } POST /students/_doc { "id":2, "name":"沸羊羊", "info":"吃阿里嘎多美羊羊桑" } POST /students/_doc { "id":3, "name":"美羊羊", "info":"沸羊羊,你八嘎呀lua" } POST /students/_doc { "id":4, "name":"李青", "info":"一庫一庫" } POST /students/_doc { "id":5, "name":"亞索", "info":"面對疾風吧" }
2、搜索方式
-
查詢所有文檔
GET /students/_search { "query": { "match_all": {} } }
-
將查詢條件分詞后再進行搜索
GET /students/_search { "query": { "match": { "info":"阿里嘎多" } } }
即將跟分詞后的結果,一個一個進行搜索。
-
ES糾錯功能(即模糊查詢)
GET /students/_search { "query": { "match": { "info":{ "query": "lue", "fuzziness": 1//最多錯誤字符數(shù),不能超過2 } } } }
使用match方式可以實現(xiàn)模糊查詢,但是模糊查詢對中文的支持效果一般。
-
對數(shù)字類型的字段進行范圍搜索
GET /students/_search { "query": { "range": { "id": { "gte": 1, "lte": 3 } } } }
此時gt是大于,lt是小于,后面的e是等于。
-
短語檢索,搜索條件不做任何分詞解析,在搜索字段對應的倒排索引中精確匹配。
GET /students/_search { "query": { "match_phrase": { "info": "八嘎" } } }
它用于關鍵詞檢索,但是得是分詞器認為是關鍵詞才算是關鍵詞,例如美羊羊就不算,但是沸羊羊就算。也可以在ik的擴展詞文件中去設置關鍵詞。
-
單詞/詞組搜索。搜索條件不做任何分詞解析,在搜索字段對應的倒排索引中精確匹配。
1)單詞搜索GET /students/_search { "query": { "term": { "info": "疾風" } } }
單詞搜索時跟短語檢索很像。但是此時沸羊羊在單詞這邊查詢不到,估計是單詞時,條件的字符數(shù)不超過2個。
2)詞組搜索GET /students/_search { "query": { "terms": { "info": ["疾風","沸"] } } }
可以多個單詞分別作為條件同時搜索。
-
復合搜索
1)must,多個搜索方式必須都滿足GET /students/_search { "query": { "bool": { "must": [ { "term":{ "info": "嘎" } }, { "range": { "id": { "gte": 2, "lte": 4 } } } ] } } }
2)should,多個搜索方式任意滿足一個
GET /students/_search { "query": { "bool": { "should": [ { "term":{ "info": "嘎" } }, { "range": { "id": { "gte": 2, "lte": 4 } } } ] } } }
3)must_not,多個搜索方式都必須不滿足
GET /students/_search { "query": { "bool": { "must": [ { "term":{ "info": "嘎" } } ], "must_not": [ { "range": { "id": { "gte": 1, "lte": 2 } } } ] } } }
3、ES搜索文檔的過濾處理
3.1 結果排序
-
默認排序,是根據(jù)查詢條件的匹配度分數(shù)進行排序的
GET /students/_search { "query": { "match": { "info": "阿里噶多美羊羊桑" } } }
-
按照id進行升序排序
GET /students/_search { "query": { "match": { "info": "阿里噶多美羊羊桑" } }, "sort": [ { "id": { "order": "asc" } } ] }
降序則把asc改成desc。
3.2 分頁查詢
-
將查詢結果從from條開始(不包括from),到from+size條結束(包括from+size)
GET /students/_search { "query": { "match_all": {} }, "from": 0, "size": 2 }
3.3 高亮查詢
-
為查詢的關鍵詞設置高亮,即在關鍵詞前面和后面加上后綴,再由前端的CS代碼設置。
GET /students/_search { "query": { "match": { "info": "面對一庫阿里噶多美羊羊桑" } }, "highlight": { "fields": { "info": { "fragment_size": 100,//返回高亮數(shù)據(jù)的最大長度 "number_of_fragments": 5 //返回結果最多可以包含幾段不連續(xù)的文字 } }, "pre_tags": ["<em>"], "post_tags": ["</em>"] } }
3.4 SQL查詢
在ES7之后,支持SQL語句查詢文檔,但是只支持部分SQL語句。并且開源版本不支持Java操作SQL進行查詢。
- 使用簡單的SQL語句查詢文檔
GET /_sql?format=txt { "query": "SELECT * FROM students" }
三、原生JAVA操作ES
1、搭建項目
-
創(chuàng)建一個空項目
-
在空項目下創(chuàng)建一個maven模塊
-
在maven模塊項目中的pom.xml文件中引入依賴
<dependencies> <!-- es --> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>7.17.9</version> </dependency> <!-- es客戶端 --> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.17.9</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> </dependencies>
因為最新的客戶端只更新到8.0,但是好像不能用,只能用7.17.9版本。
2、索引操作
-
創(chuàng)建一個空索引
//創(chuàng)建空索引 @Test public void createIndex() throws IOException { //1.創(chuàng)建客戶端對象,連接ES RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.126.24", 9200, "http"))); //2.創(chuàng)建請求對象 CreateIndexRequest studentx = new CreateIndexRequest("studentx"); //3.發(fā)送請求 CreateIndexResponse response = client.indices().create(studentx, RequestOptions.DEFAULT); //4.操作響應結果 System.out.println(response.index()); //5.關閉客戶端 client.close(); }
-
給空索引添加結構
//給索引添加結構 @Test public void mappingIndex() throws IOException { //1.創(chuàng)建客戶端對象,連接ES RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.126.24", 9200, "http"))); //2.創(chuàng)建請求對象 PutMappingRequest request = new PutMappingRequest("studentx"); request.source(" {\n" + " \"properties\": {\n" + " \"id\": {\n" + " \"type\": \"integer\"\n" + " },\n" + " \"name\": {\n" + " \"type\": \"text\"\n" + " },\n" + " \"age\": {\n" + " \"type\": \"integer\"\n" + " }\n" + " }\n" + " }", XContentType.JSON); //3.發(fā)送請求 AcknowledgedResponse response = client.indices().putMapping(request, RequestOptions.DEFAULT); //4.操作響應結果 System.out.println(response.isAcknowledged()); //5.關閉客戶端 client.close(); }
-
刪除索引
//刪除索引 @Test public void deleteIndex() throws IOException { //1.創(chuàng)建客戶端對象,連接ES RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.126.24", 9200, "http"))); //2.創(chuàng)建請求對象 DeleteIndexRequest request = new DeleteIndexRequest("studentx"); //3.發(fā)送請求 AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT); //4.操作響應結果 System.out.println(response.isAcknowledged()); //5.關閉客戶端 client.close(); }
3、文檔操作
-
新增/修改文檔操作
// 新增/修改文檔 @Test public void addDocument() throws IOException { //1.創(chuàng)建客戶端對象,連接ES RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.126.24", 9200, "http"))); //2.創(chuàng)建請求對象 IndexRequest request = new IndexRequest("studentx").id("1"); request.source(XContentFactory.jsonBuilder() .startObject() .field("id",1) .field("name","z z x") .field("age",18) .endObject()); //3.發(fā)送請求 IndexResponse response = client.index(request, RequestOptions.DEFAULT); //4.操作響應結果 System.out.println(response.status()); //5.關閉客戶端 client.close(); }
新增文檔成功,但是報了個錯Unable to parse response body for Response,意思是無法解析響應的正文。有可能是ES服務用的是8.6.1,但是JAVA依賴的版本是7.17.9,版本不一致導致的。
-
根據(jù)id查詢文檔
// 根據(jù)id查詢文檔 @Test public void findByIdDocument() throws IOException { //1.創(chuàng)建客戶端對象,連接ES RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.126.24", 9200, "http"))); //2.創(chuàng)建請求對象 GetRequest request = new GetRequest("studentx", "1"); //3.發(fā)送請求 GetResponse response = client.get(request, RequestOptions.DEFAULT); //4.操作響應結果 System.out.println(response.getSourceAsString()); //5.關閉客戶端 client.close(); }
-
刪除文檔
// 刪除文檔 @Test public void deleteDocument() throws IOException { //1.創(chuàng)建客戶端對象,連接ES RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.126.24", 9200, "http"))); //2.創(chuàng)建請求對象 DeleteRequest request = new DeleteRequest("studentx", "1"); //3.發(fā)送請求 DeleteResponse response = client.delete(request, RequestOptions.DEFAULT); //4.操作響應結果 System.out.println(response.status()); //5.關閉客戶端 client.close(); }
4、搜索文檔
-
查找所有文檔文章來源:http://www.zghlxwxcb.cn/news/detail-778398.html
// 搜索所有文檔 @Test public void queryAllDocument() throws IOException { //1.創(chuàng)建客戶端對象,連接ES RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.126.24", 9200, "http"))); //2.創(chuàng)建搜索條件 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchAllQuery()); //3.創(chuàng)建請求對象 SearchRequest request = new SearchRequest("studentx").source(searchSourceBuilder); //4.發(fā)送請求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); //5.操作響應結果 SearchHits hits = response.getHits(); for (SearchHit hit:hits) { System.out.println(hit.getSourceAsString()); } //6.關閉客戶端 client.close(); }
-
根據(jù)關鍵詞搜索文檔文章來源地址http://www.zghlxwxcb.cn/news/detail-778398.html
// 根據(jù)關鍵詞搜索文檔 @Test public void queryTermDocument() throws IOException { //1.創(chuàng)建客戶端對象,連接ES RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.126.24", 9200, "http"))); //2.創(chuàng)建搜索條件 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.termQuery("name","x")); //3.創(chuàng)建請求對象 SearchRequest request = new SearchRequest("studentx").source(searchSourceBuilder); //4.發(fā)送請求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); //5.操作響應結果 SearchHits hits = response.getHits(); for (SearchHit hit:hits) { System.out.println(hit.getSourceAsString()); } //6.關閉客戶端 client.close(); }
總結:
- 1)默認分詞器是standard analyzer,是英文分詞器,根據(jù)空格和標點符號對應英文進行分詞,會進行單詞的大小寫轉換。
2)IK分詞器,是中文分詞器,分別有兩種算法ik_smart:最少切分,即一段話中的字只會被劃分一次;ik_max_word:最細粒度劃分,即一段話中的字可能會被劃分多次。IK分詞器中可以在IKAnalyzer.cfg.xml文件中配置自定義詞庫,其中ext_stopwords是停用詞,即不使用;ext_dict是擴展詞,即使用。
3)拼音分詞器,將中文進行轉換成拼音并且進行分詞。即單個文字以及整段文字的拼音進行分詞。
4)自定義分詞器可以將ik和拼音分詞器進行一個組合,將ik分詞器分詞后的結果讓拼音分詞器再進行分詞。 - GET /students/_search,即GET + 索引+ _search是用來搜索文檔的固定格式。
1)搜索方式有match_all,即搜索該索引全部的文檔。
match,根據(jù)查詢條件分詞后,再按分詞的結果一個一個查詢,并且match可以實現(xiàn)模糊查詢,但是錯誤的字符數(shù)量不能超過兩個,使用fuzziness設置。
range,對數(shù)字類型的字段進行范圍搜索,gt是大于,lt是小于,后面的e是等于。
match_phrase,關鍵詞搜索,此時你的搜索條件要與分詞器分詞后的結果相同才會查詢到結構,并且它是精確搜索,不會再分詞。
term是單詞搜索,條件的字符數(shù)不超過2個,也就是說可能match_phare的搜索范圍是包含term的。
terms是詞組搜索,可以多個單詞分別作為條件同時搜索。
復合搜索,must,多個搜索方式必須都滿足;should,多個搜索方式任意一個滿足;must_not,多個條件都必須不滿足。 - 由于ES對text類型字段數(shù)據(jù)會做分詞處理,使用哪個單詞做排序都是不合理的,所以ES中默認不允許text類型的字段做排序,可以使用keyword類型的字段作為排序依據(jù),因為keyword字段不做分詞處理。
ES默認排序是按查詢條件的相關度分數(shù)排序,也可以使用sort,依據(jù)字段做升序和降序的排序。
使用from和size進行分頁查詢,從from(不包括from)位置開始到from+size位置結束。
highlight,為查詢的關鍵詞設置高亮,即在關鍵詞前面和后面加上后綴,再由前端的CS代碼設置。
在ES7之后,支持SQL語句查詢文檔,但是只支持部分SQL語句。并且開源版本不支持Java操作SQL進行查詢。 - 原生JAVA操作ES時,索引操作時,使用CreateIndexRequest,PutMappingRequest,DeleteIndexRequest類進行索引的操作。
文檔操作時,使用IndexRequest,GetRequest,DeleteRequest類進行文檔的操作。
搜索文檔時,使用SearchRequest類進行搜索的操作。
每次訪問ES時,都需要創(chuàng)建客戶端對象去連接ES,創(chuàng)建請求對象,發(fā)送請求到ES,然后ES返回一個響應,對這個響應進行處理,最后關閉這個客戶端。
到了這里,關于Elasticsearch_分詞器、搜索文檔以及原生JAVA操作的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!