ElasticSearch再學習

ElasticSearch參數詳解

本次使用的windows的版本,如若Linux移步:http://www.javashuo.com/article/p-diqcjiyk-s.htmlhtml

配置文件參數

首先咱們對ES的解壓目錄作一個簡單的瞭解:json

  

而後就是配置文件目錄中的三個配置文件作一個說明:bootstrap

  • elasticsearch.ymlwindows

    點擊進去裏面的配置全是被註釋掉的,咱們能夠加入下面的數據做爲配置api

  • jvm.options數組

    有關JVM屬性的配置,通常咱們就設置堆的最小最大值,通常設爲相等,不能超過物理內存的一半緩存

    -Xms2g -Xmx2gapp

  • log4j2.propertiesjvm

    日誌文件的配置,ES使用log4j,配置一下日誌級別就OKelasticsearch

面向Restful的api接口

  • 建立索引庫

    put http://localhost:9200/索引庫名稱

    • number_of_shards:設置分片的數量,在集羣中一般設置多個分片,表示一個索引庫將拆分紅多片分別存儲不一樣的結點,提升了ES的處理能力和高可用性,入門程序使用單機環境,這裏設置爲1。

    • number_of_replicas:設置副本的數量,設置副本是爲了提升ES的高可靠性,單機環境設置爲0.

  • 建立映射

    post http://localhost:9200/索引庫名稱/類型名稱/_mapping

    • 類型名稱暫時沒有意義存在,隨便取一個便可,好比doc這種沒有意義的

  • 插入文檔

    put 或Post http://localhost:9200/索引庫名稱/類型名稱/文檔id

    關於最後的文檔id,咱們若是有設置就會使用咱們本身的,若不設置,ES會自動生成

  • 搜索文檔

    根據文檔id查詢:

    查詢全部文檔:

    根據某個屬性的的值插敘:

    • get http://localhost:9200/索引庫名稱/類型名稱/_search?q=name:bootstrap

    • 根據name屬性的值爲bootstrap進行查詢,前面固定格式

  • 查詢結果參數解析

    查詢結果通常會有以下數據顯示

IK分詞器

簡單上手

ES默認自帶的分詞器對於中文而言是單字分詞,好比我愛祖國,ES會一個字一個字的分詞,這樣很明顯不行

咱們查看下面的分詞效果

post:localhost:9200/_analyze

{"text":"測試分詞器,我愛祖國"}

ES在以前的文件目錄說明哪裏也有說到,ES是支持插件機制的,咱們將IK丟pligins包裏就好,記得重啓ES

咱們手動指定使用的分詞器,查看下面的分詞效果

post:localhost:9200/_analyze

{"text":"測試分詞器,我愛我本身","analyzer":"ik_max_word"}

而後發現好像有點複合咱們國人的口味了,這裏ik分詞有兩個模式

  • ik_max_word ,這個就是咱們上面使用到的一個模式,劃分粒度比較細,通常用於存儲的時候,進行分詞存儲索引

  • ik_smart ,相對而言,這個就要粗曠一些了,通常在檢索索引時,對檢索條件的字段進行粗曠的分詞

    好比:下面這句話的意思就是name屬性在索引和在搜索時都是用ik_max_word模式

    "name": { "type": "text", "analyzer":"ik_max_word" }

    再好比:索引時使用「ik_max_word」分詞,搜索時使用「ik_smart」提升搜索精確性

    "name": { "type": "text", "analyzer":"ik_max_word", "search_analyzer":"ik_smart" }

自定義詞庫

有一些特殊的領域是有一些專有的詞語的,而Ik是分辨不出來,因此這裏須要使用到IK的自定義詞庫

  • 首先定義咱們本身的詞庫:my.dic

    記得保存爲UTF-8格式,否則讀取不到

  • 而後咱們再配置文件中去加載咱們的自定義詞庫:IKAnalyzer.cfg.xml

  • 而後重啓ES,查看分詞效果

post:localhost:9200/_analyze

{"text":"死亡野格兒","analyzer":"ik_max_word"}

映射

  • 映射一旦建立,已有的映射是不容許更改,只能新增或者刪除重建

  • 刪除映射也只能經過刪除索引來完成

映射的類型_text

核心的字段類型:

映射的類型選好了,還有一些其餘的屬性能夠設置

  • analyzer :經過該屬性指定分詞器及模式

    name屬性的類型爲text,在索引時使用「ik_max_word」分詞器模式

    在搜索時使用"ik_smart "分詞器模式分詞

    通常都是建議在索引的時候詞語最細化,在搜索時,對搜索條件粗曠化提升搜索精度

  • index:經過該屬性指定是否索引,默認爲true

    只有在設置爲false時,該屬性的值是不會存入索引庫的,也不會被檢索到

    好比pic屬性表示的是圖片的地址,通常咱們不uhi把這個地址做爲搜索條件進行檢索,故而設置爲false

  • store:額外存儲,通常不用理會

    是否在source以外存儲,每一個文檔索引後會在 ES中保存一份原始文檔,存放在"source"中,通常狀況下不須要設置 store爲true,由於在source中已經有一份原始文檔了。

映射的類型_keyword關鍵字

上面咱們說明了text類型的屬性在映射時均可以is盒子分詞器,keyword字段是一個關鍵字字段,一般搜索keyword是按照總體搜索的,是不會作分詞,因此查詢的時候是須要精確匹配的,好比郵政編碼,身份證號等是不會且不該該作分詞的,keywoed文本通常用於過濾,排序,聚合等場合

  • 映射以下:

  • 插入文檔

  • 根據name或者身份證號查詢

    Get:http://localhost:9200/索引庫/類型名稱/_search?q=name:狗剩兒

    這樣是查詢不到的,由於name屬性是keyword類型,必須精確匹配

映射的類型_data日期類型

日期類型也是不用設置分詞器的一種類型,通常日期類型用於排序

經過format設置日期的格式,上面的這個列子容許date字段儲存年月日時分秒||年月日這兩種格式

插入文檔以下:Post:Post :http://localhost:9200/索引庫/類型名/文檔id

{ "time":"2018‐08‐15 20:28:58" }

映射的類型_數值類型

  • 儘可能選擇範圍曉得類型,提升檢索效率節省空間

  • 對於浮點數,儘可能用比列因子,好比一個雞蛋的單價是1.2元/個,咱們將別列因子設置爲100,這在ES中會按照分儲存,映射以下:

由於咱們將比列因子設置爲100,因此儲存的時候,會將1.2 * 100 進行儲存

使用比列因子的好處就在與整型比浮點型更容易壓縮,節約空間,固然若是比列因子不合適,咱們再選範圍小的去存

ES客戶端(Java)

  • pom.xml:核心依賴

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>6.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>6.2.1</version>
        </dependency>
  • Spring容器注入客戶端

    注意這裏注入兩個版本的客戶端一個是高版本,推薦使用的RestHighLevelClient,但功能可能不是很完善

    RestClient低版本的客戶端,當咱們高版本的客戶端不能使用時,考慮使用這個

@Configuration public class ElasticsearchConfig { ​ @Value("${test.elasticsearch.hostlist}") private String hostlist; ​ //獲取高版本的客戶端
 @Bean public RestHighLevelClient restHighLevelClient(){ //解析hostlist配置信息
        String[] split = hostlist.split(","); //建立HttpHost數組,其中存放es主機和端口的配置信息
        HttpHost[] httpHostArray = new HttpHost[split.length]; for(int i=0;i<split.length;i++){ String item = split[i]; httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http"); } //建立RestHighLevelClient客戶端
        return new RestHighLevelClient(RestClient.builder(httpHostArray)); } ​ //項目主要使用RestHighLevelClient,對於低級的客戶端暫時不用
 @Bean public RestClient restClient(){ //解析hostlist配置信息
        String[] split = hostlist.split(","); //建立HttpHost數組,其中存放es主機和端口的配置信息
        HttpHost[] httpHostArray = new HttpHost[split.length]; for(int i=0;i<split.length;i++){ String item = split[i]; httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http"); } return RestClient.builder(httpHostArray).build(); } }

建立索引庫

首先注入Java客戶端,咱們使用第一個便可:

 //高版本的客戶端
 @Autowired RestHighLevelClient highClient; //低版本的客戶端
 @Autowired RestClient restClient; //建立索引庫
 @Test public void CreateIndexTest() throws IOException { //建立索引請求對象,並設置索引名稱
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("test_index"); //設置索引參數
        createIndexRequest.settings(Settings.builder().put("number_of_shards",1) .put("number_of_replicas",0)); //設置映射
        createIndexRequest.mapping("doc"," {\n" +
                " \t\"properties\": {\n" +
                " \"name\": {\n" +
                " \"type\": \"text\",\n" +
                " \"analyzer\":\"ik_max_word\",\n" +
                " \"search_analyzer\":\"ik_smart\"\n" +
                " },\n" +
                " \"description\": {\n" +
                " \"type\": \"text\",\n" +
                " \"analyzer\":\"ik_max_word\",\n" +
                " \"search_analyzer\":\"ik_smart\"\n" +
                " },\n" +
                " \"studymodel\": {\n" +
                " \"type\": \"keyword\"\n" +
                " },\n" +
                " \"price\": {\n" +
                " \"type\": \"float\"\n" +
                " }\n" +
                " }\n" +
                "}", XContentType.JSON); //建立索引操做客戶端
        IndicesClient indices = highClient.indices(); //建立響應對象
        CreateIndexResponse createIndexResponse = indices.create(createIndexRequest); //獲得響應結果
        boolean acknowledged = createIndexResponse.isAcknowledged(); System.out.println(acknowledged); }

添加文檔

查詢文檔

更新文檔

刪除文檔

搜索 [ 核心用法 ]

環境準備

首先咱們建立一個名爲「test_index」的索引庫

並建立以下索引:

插入如下數據做爲測試數據:id分別爲一、二、3

最基本的搜索咱們前面意思使用過了:

  • 以這樣的格式: get ../_search?q=.....

DSL_搜索介紹

  • DSL:"Domain Specific Language "

  • 是ES提出的基於json的搜索方式,在搜索時鍵入特定的json格式的數據來哇稱搜索,所有POST請求

  • 通常項目中都是使用的DSL搜索

DSL_查詢全部文檔

@Test public void queryAllTest() throws IOException { //建立搜索請求對象,綁定索引庫和類型
        SearchRequest searchRequest = new SearchRequest("test_index"); searchRequest.types("doc"); ​ //建立:搜索源構建對象
        SearchSourceBuilder builder = new SearchSourceBuilder(); //指定搜索方式:matchAllQuery
 builder.query(QueryBuilders.matchAllQuery()); //設置源字段過濾,第一個數組表示要包含的字段,第二個數組表示不包括的字段
        builder.fetchSource(new String[]{"name","studymodel"},new String[]{}); //向搜索請求中設置搜索源
 searchRequest.source(builder); //使用客戶端發起搜索,得到結果
        SearchResponse searchResponse = highClient.search(searchRequest); //搜索結果
        SearchHits hits = searchResponse.getHits(); //從搜索結果中獲得 : 匹配分高位於前面的文檔
        SearchHit[] searchHits = hits.getHits(); for (SearchHit hit : searchHits) { Map<String, Object> map = hit.getSourceAsMap(); System.out.println(map.get("name")); System.out.println(map.get("studymodel")); } }

使用注意事項:

  • 在咱們設置源字段過濾的時候,咱們只選取了着兩個字段,當咱們獲取對結果後,也只能獲取這兩個字段的數據

DSL_分頁查詢

不分詞精確查詢Term Query

Term Query爲精確查詢,在搜索時會總體匹配關鍵字,再也不將關鍵字分詞作搜索

根據Id精確匹配:ids

  • 請求方式:根據id 1和2精確匹配數據

  • Java,注意事項已經在圖片中給出

分詞全文檢索:match Query

match Query:全文檢索,先對咱們搜索的詞條進行分詞,而後將分好的詞再拿去意義匹配查詢

Term Query是不作分詞,match Query是要作分詞,這裏作個對比,利於記憶

在這個請求中,query的值爲咱們搜索的關鍵詞,會被分詞,在這個列子中會被分爲「是」、「一」兩個字

operator:咱們分詞後出現了兩個詞條,只要有一個詞條匹配上就命中,與之相應的還有and,表示兩個或多個詞條必須同時匹配上才能命中,在這裏還有擴展,好比咱們搜索的關鍵字分詞後爲三個字,是一個字匹配上就命中呢?仍是兩個字匹配上算命中呢?仍是所有匹配詞條匹配上才能算命中呢?ES提供了佔比的方式來檢索數據,見下:

minimum_should_match :關鍵字檢索分詞時,匹配文檔的關鍵字分詞詞條百分比指定

"是一個"這個詞再被分詞時,ik會把它分爲四個詞,分別爲:"是"、"一"、"一個"、"個";

咱們設的80%,表示的意思,一共4個詞條,佔比8成爲 4 * 80% = 3.2 取整爲3,表示命中的文檔必須有三個詞條匹配上

多個字段分詞檢索:multi Query

上面的Term Query 和match Query一次只能對一個關鍵詞做分詞檢索,multi Query能夠對多個關鍵詞作分詞檢索

擴展玩法:提高權重boost

 

搜索關鍵詞是"Spring開發",在咱們檢索該條數據的時候,通常但願的的是名字爲"Spring開發",而不是描述中包含這個關鍵字,因此咱們想提升這個關鍵字在搜索時,對於name字段作特殊照顧,這樣就能夠將name字段與Spring開發匹配上的文檔得分提升,排在命中的前面

布爾查詢:bool

布爾查詢實現將多個查詢組合起來

三個參數

  • must:文檔必須匹配must所包含的查詢條件

  • should:文檔必須匹配should所包含的條件的一個或多個

  • must_not:文檔不能匹配must_not包含的任意一個查詢條件

    下面這個列子自行替換關鍵字進行測試

有點繞,我給圈出來了,很好看明白。

過濾器:filter

含義就很重要,須要劃線要考:是針對結果進行過濾

過濾器的做用爲判斷該文檔是否匹配,不會去計算匹配得分,性能比查詢要高,緩存也方便,推薦的話:

儘可能使用過濾器是顯示查詢或者經過過濾器 + 查詢共同檢索

過濾器在布爾查詢中使用:

  • filter:過濾,term和range一次只能對一個字段進行設置過濾條件

  • term:項匹配過濾,留下studymodel爲201004的文檔

  • range:範圍查詢,價格price>60 且 <100的文檔

排序:sort

能夠對一個字段進行設置排序,支持在keyword,date,float等類型上添加排序,text不容許排序

過濾價格在0—100區間的全部文檔,優先按照studymodel降序排序,其次在根據價格升序排序

高亮顯示:highlight

高亮顯示能夠將搜索結果一個或多個字突出顯示,以便向用戶展現匹配關鍵字的位置

在搜索語句中添加highlight便可實現,這個我把檢索結果也貼出來方便查看

---------------------------------------------------------------------

最後由於咱們只獲取了高亮裏面的name:ElasticSearch<tag1>開發</tag2><tag1>學習</tag2>

由於可讀性,Json我都是截圖的的方式展現的,索性代碼也是截圖了,後續可能還有補充......

獻上Es相關的資源:https://pan.baidu.com/s/10LZyR2jX2WAnEsLibHLAfA   提取碼:yc90 

相關文章
相關標籤/搜索