天天看點

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

一、檢索概述

應用經常需要添加檢索功能,開源的 ElasticSearch 是目前全文搜尋引擎的首選。他可以快速的存儲、搜尋和分析海量資料。Spring Boot通過整合Spring Data ElasticSearch為我們提供了非常便捷的檢索功能支援;

Elasticsearch是一個分布式搜尋服務,提供Restful API,底層基于Lucene,采用多shard(分片)的方式保證資料安全,并且提供自動resharding的功能,github等大型的站點也是采用了ElasticSearch作為其搜尋服務。

官方文檔

二 、使用docker安裝Elasticsearch

docker pull elasticsearch:7.4.2 下載下傳鏡像

docker pull kibana:7.4.2 下載下傳kibana可視化 界面

docker images 檢視下載下傳好了哪些鏡像

docker ps 檢視正在運作的服務

free -m 檢視虛拟機可用記憶體

mkdir -p /mydata/elasticsearch/config --建立目錄

mkdir -p /mydata/elasticsearch/data --建立目錄

echo “http.host: 0.0.0.0” >> /mydata/elasticsearch/config/elasticsearch.yml --在elasticsearch.yml中配置在任何ip位址可以通路es服務,這裡的冒号後面有一個空格

chmod -R 777 /mydata/elasticsearch/ –修改目錄權限

–建立容器并啟動且檔案挂載

使用9200端口通路傳回json資料說明成功

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

注:此處請關閉防火牆(關閉後重新開機docker)systemctl stop firewalld

檢視防火牆狀态systemctl status firewalld

安裝kibana可視化界面

docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.20.66:9200 -p 5601:5601

-d kibana:7.4.2

稍等kibana徹底啟動後通路5601端口:看到以下界面代表成功

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

配置elasticsearch和kibana開機啟動

docker update 容器id --restart=always

注意Elasticsearch版本應該與springboot版本比對

版本适配說明:版本适配說明

應安裝Spring Data 對應版本的ElasticSearch

預設的ElasticSearch的web端口為9200

分布式節點之間通信使用的接口為9300

使用ElasticSearch會占用2G的記憶體空間為防止記憶體溢出是以這裡設定其大小。

此處記一坑

通過docker指令開啟elasticsearch7.5通路9200被拒絕elasticsearch7.5服務會自動關閉,可通過docker logs -f 容器id檢視日志日志顯示

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

解決方法:

檢視虛拟機是否安裝jdk:

執行liunx指令:

vi /etc/sysctl.conf

在檔案末尾添加:

vm.max_map_count=262144

執行liunx指令,立即執行

/sbin/sysctl -p

啟動再次秒退檢視容器日志

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

降低elasticsearch版本為6.5.0通路9200端口成功

三、Elasticsearch中的幾個概念

反向索引:将我們要存儲的一個短語進行分詞處理得到多個分詞,并将索引的位置存放到各個分詞中;

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

與資料庫類比:

  • 索引-資料庫
  • 類型-表 這裡的類型概念在elasticsearch7.0之後被删除不再使用,在下面的第五-》4.mapping映射 中會說明 原因
  • 文檔-表中的記錄
  • 屬性-列
    進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

3.1 核心概念

3.1.1 索引(Index)

一個索引就是一個擁有幾分相似特征的文檔的集合。比如說,你可以有一個客戶資料的索引,另一個産品目錄的索引,還有一個訂單資料的索引。一個索引由一個名字來辨別(必須全部是小寫字母),并且當我們要對這個索引中的文檔進行索引、搜尋、更新和删除的時候,都要使用到這個名字。在一個叢集中,可以定義任意多的索引。

能搜尋的資料必須索引,這樣的好處是可以提高查詢速度,比如:新華字典前面的目錄就是索引的意思,目錄可以提高查詢速度。

Elasticsearch索引的精髓:一切設計都是為了提高搜尋的性能。

3.1.2 類型(Type)

在一個索引中,你可以定義一種或多種類型。

一個類型是你的索引的一個邏輯上的分類/分區,其語義完全由你來定。通常,會為具有一組共同字段的文檔定義一個類型。不同的版本,類型發生了不同的變化

版本 Type:5.x支援多種type 6.x 隻能有一種type 7.x 預設不再支援自定義索引類型(預設類型為:_doc)

3.1.3 文檔(Document)

一個文檔是一個可被索引的基礎資訊單元,也就是一條資料

比如:你可以擁有某一個客戶的文檔,某一個産品的一個文檔,當然,也可以擁有某個訂單的一個文檔。文檔以JSON(Javascript Object Notation)格式來表示,而JSON是一個到處存在的網際網路資料互動格式。

在一個index/type裡面,你可以存儲任意多的文檔。

3.1.4 字段(Field)

相當于是資料表的字段,對文檔資料根據不同屬性進行的分類辨別。

3.1.5 映射(Mapping)

mapping是處理資料的方式和規則方面做一些限制,如:某個字段的資料類型、預設值、分析器、是否被索引等等。這些都是映射裡面可以設定的,其它就是處理ES裡面資料的一些使用規則設定也叫做映射,按着最優規則處理資料對性能提高很大,是以才需要建立映射,并且需要思考如何建立映射才能對性能更好。

3.1.6 分片(Shards)

一個索引可以存儲超出單個節點硬體限制的大量資料。比如,一個具有10億文檔資料的索引占據1TB的磁盤空間,而任一節點都可能沒有這樣大的磁盤空間。或者單個節點處理搜尋請求,響應太慢。為了解決這個問題,Elasticsearch提供了将索引劃分成多份的能力,每一份就稱之為分片。當你建立一個索引的時候,你可以指定你想要的分片的數量。每個分片本身也是一個功能完善并且獨立的“索引”,這個“索引”可以被放置到叢集中的任何節點上。

分片很重要,主要有兩方面的原因:

  • 允許你水準分割 / 擴充你的内容容量。
  • 允許你在分片之上進行分布式的、并行的操作,進而提高性能/吞吐量。

    至于一個分片怎樣分布,它的文檔怎樣聚合和搜尋請求,是完全由Elasticsearch管理的,對于作為使用者的你來說,無需過分關心。

    被混淆的概念是,一個 Lucene 索引我們在 Elasticsearch 稱作 分片 。 一個Elasticsearch 索引是分片的集合。 當 Elasticsearch 在索引中搜尋的時候, 他發送查詢到每一個屬于索引的分片(Lucene 索引),然後合并每個分片的結果到一個全局的結果集。

3.1.7 副本(Replicas)

在一個網絡 / 雲的環境裡,失敗随時都可能發生,在某個分片/節點不知怎麼的就處于離線狀态,或者由于任何原因消失了,這種情況下,有一個故障轉移機制是非常有用并且是強烈推薦的。為此目的,Elasticsearch允許你建立分片的一份或多份拷貝,這些拷貝叫做複制分片(副本)。

複制分片之是以重要,有兩個主要原因:

  • 在分片/節點失敗的情況下,提供了高可用性。因為這個原因,注意到複制分片從不與原/主要(original/primary)分片置于同一節點上是非常重要的。
  • 擴充你的搜尋量/吞吐量,因為搜尋可以在所有的副本上并行運作。

    總之,每個索引可以被分成多個分片。一個索引也可以被複制0次(意思是沒有複制)或多次。一旦複制了,每個索引就有了主分片(作為複制源的原來的分片)和複制分片(主分片的拷貝)之别。分片和複制的數量可以在索引建立的時候指定。在索引建立之後,你可以在任何時候動态地改變複制的數量,但是你事後不能改變分片的數量。預設情況下,Elasticsearch中的每個索引被分片1個主分片和1個複制,這意味着,如果你的叢集中至少有兩個節點,你的索引将會有1個主分片和另外1個複制分片(1個完全拷貝),這樣的話每個索引總共就有2個分片,我們需要根據索引需要确定分片個數。

3.1.8 配置設定(Allocation)

将分片配置設定給某個節點的過程,包括配置設定主分片或者副本。如果是副本,還包含從主分片複制資料的過程。這個過程是由master節點完成的。

3.2 系統架構

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

一個運作中的 Elasticsearch 執行個體稱為一個節點,而叢集是由一個或者多個擁有相同cluster.name 配置的節點組成, 它們共同承擔資料和負載的壓力。當有節點加入叢集中或者從叢集中移除節點時,叢集将會重新平均分布所有的資料。

當一個節點被選舉成為主節點時, 它将負責管理叢集範圍内的所有變更,例如增加、删除索引,或者增加、删除節點等。 而主節點并不需要涉及到文檔級别的變更和搜尋等操作,是以當叢集隻擁有一個主節點的情況下,即使流量的增加它也不會成為瓶頸。 任何節點都可以成為主節點。我們的示例叢集就隻有一個節點,是以它同時也成為了主節點。

作為使用者,我們可以将請求發送到叢集中的任何節點 ,包括主節點。 每個節點都知道任意文檔所處的位置,并且能夠将我們的請求直接轉發到存儲我們所需文檔的節點。 無論我們将請求發送到哪個節點,它都能負責從各個包含我們所需文檔的節點收集回資料,并将最終結果傳回給用戶端。 Elasticsearch 對這一切的管理都是透明的。

測試Elasticsearch的幾個常用操作

這裡為了友善使用postman模拟web應用發送的請求

  • 索引一個員工文檔
    進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

    _index:索引名

    _type:文檔類型

    _id:文檔id

    _version:版本号

    _source:文檔内容

  • 檢索操作
  1. 檢索員工文檔中id為1的文檔

    GET http://192.168.1.5:9200/megacorp/employee/1

  2. 檢索所有員工文檔

    GET http://192.168.1.5:9200/megacorp/employee/_search

  3. 檢索員工文檔中姓氏為Smith的

    GET http://192.168.1.5:9200/megacorp/employee/_search?q=last_name:Smith

  4. 使用查詢表達式搜尋姓氏為Smith的
    進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)
  • 删除索引中文檔id為3的員工文檔
    進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)
    更多操作參考:使用文檔

四、初步檢索

1._cat查詢es的資訊

GET/_cat/nodes 檢視所有節點—>叢集中每個es都是一個節點

GET/_cat/health 檢視es健康狀況

GET/_cat/master 檢視主節點–>叢集中的主節點

GET/_cat/indices 檢視所有索引–>相當于show databases

2.索引一個文檔(儲存)PUT/POST

PUT或POST/megacorp/employee/1---------攜帶的資料使用json類型

post:新增時可以不攜帶id,自動生成id;若攜帶id但該id之前已經存在資料就會執行覆寫操作并修改版本号,若不存在則會新增資料

put :必須攜帶id唯一辨別進行儲存操作,若id已存在就執行修改并修改版本号,若不存在執行新增

我們在索引一個對象數組時es會将我們的數組進行扁平化

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

使用嵌入式屬性解決扁平化處理導緻的錯誤,需要在建立索引時為屬性指定type為nested

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

3.查詢文檔GET

GET /megacorp/employee/1

_index:在哪個索引名

_type:在哪個文檔類型

_id:文檔id

_version:版本号

_seq_no:序列号,并發控制字段,每次更新就會+1,用來做樂觀鎖

_primary_term:主分片重新配置設定,如重新開機會變化

_source:真正的内容

4.更新文檔

POST/megacorp/employee/_update 攜帶的資料使用json類型使用{“doc”:{屬性名:屬性值}}包裹攜帶的資料

更新操作會對比原資料,若資料無改變,版本号與序列号就不會發生變化

若在請求時不攜帶_update就不會對比資料,無論資料是否與原資料相同,版本号與序列号都會發生變化

PUT方式無論是否攜帶_update都不會對比原資料,直接更新資料

5.删除文檔

DELETE /megacorp/employee/1

隻提供删除索引與删除指定文檔不能删除某個類型

6.bulk批量API

POST /megacorp/employee/_bulk 為某個索引的某個類型批量增加索引

請求體:raw–>josn

{“index”:{"_id":2}}

{“name”:“zhangsan”}

{“index”:{"_id":3}}

{“name”:“lisi”}

批量操作都是單個操作的這裡差別于mysql的事務,即使有一個失敗了别的也會正常運作

五、進階檢索

準備資料:https://github.com/elastic/elasticsearch/blob/master/docs/src/test/resources/accounts.json

将資料索引到bank/account下

POST /bank/account/_bulk 請求體為網址中的josn資料

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

官方文檔

es支援兩種基本檢索方式:

1.SearchAPI檢索資訊–發送搜尋參數(uri+檢索參數)

GET bank/_search?q=*&sort=account_number:asc 檢索bank索引下的所有文檔并根據賬号升序排列

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

took :Elasticsearch運作查詢多長時間(以毫秒為機關)

timed_out :搜尋請求是否逾時

_shards :搜尋了多少個分片,以及成功,失敗或跳過了多少個分片。

max_score :找到的最相關檔案的分數

hits.total.value:找到了多少個比對的文檔

hits.sort :文檔的排序位置(不按相關性得分排序時)

hits._score:文檔的相關性得分(使用時不适用match_all)

hits._source:文檔的内容

2.Query DSL(uri+請求體)

查詢表達式(Query DSL)是一種非常靈活又富有表現力的 查詢語言。 Elasticsearch 使用它可以以簡單的 JSON 接口來展現 Lucene 功能的絕大部分

基本文法

GET bank/_search

{
    "query": {			//查詢條件
        "match": {		//比對tweet字段包含elasticsearch的資料		match-all是比對所有資料
            "tweet": "elasticsearch"
        }
    },
    "sort":[{				//排序條件先按照balance字段排序,再根據account_number排序
     		"balance":{	//,指定order規則,為降序
     				"order":"desc"
     		},
     		{ 
     		"account_number": "asc" 
     		}
     }],
     "from":0,	//從第一條開始
     "size":5,	//每次取5條資料
     "_source":[{"balance","firstname"}]		//隻傳回文檔中的balance與firstname字段
}
           

使用 match 查詢語句 來查詢 tweet 字段中包含 elasticsearch 的 tweet:

查詢所有 match_all 查詢簡單的比對所有文檔。在沒有指定查詢方式時,它是預設的查詢:

全文檢索 match 若比對的字段值為數字則進行的是精确檢索(即相等的才會被查出來),

若比對的是非數字會對檢索條件進行分詞比對,隻要包含分詞的都會被查出,并按照評分(指定字元串的比對程度)進行排序。

短語比對 match_phrase 将查詢條件當作一個不可分割的短語去查詢,

多字段比對 multi_match 查詢可以在多個字段上執行相同的 match 查詢(會進行多個字段的全文檢索)

{
    "multi_match": {
        "query":    "full text search",
        "fields":   [ "title", "body" ]
    }
}
           

複合查詢 bool你可以用 bool 查詢來實作你的需求。這種查詢将多查詢組合在一起,成為使用者自己想要的布爾查詢。

它接收以下參數:

must:文檔必須比對這些條件才能被包含進來。比對到增加得分

must_not:文檔必須不比對這些條件才能被包含進來。不影響得分

should:最好滿足,如果滿足這些語句中的任意語句,将增加 _score得分,不滿足也無任何影響。

filter:必須 比對,但它以不評分、過濾模式來進行。這些語句對評分沒有貢獻,隻是根據過濾标準來排除或包含文檔。

GET /_search
{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }},
            { "range": { "date": { "gte": "2014-01-01" }}}
        ]
    }
}
           

增加帶過濾器 filter 若不想因為文檔的時間而影響得分,可以用 filter 語句來重寫

如果你需要通過多個不同的标準來過濾你的文檔,bool 查詢本身也可以被用做不評分的查詢。簡單地将它放置到 filter 語句中并在内部建構布爾邏輯:

GET /_search
{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }}
        ],
        "filter": {
          "bool": { 
              "must": [
                  { "range": { "date": { "gte": "2014-01-01" }}},
                  { "range": { "price": { "lte": 29.99 }}}
              ],
              "must_not": [
                  { "term": { "category": "ebooks" }}
              ]
          }
        }
    }
}
           

精确查詢 term 查詢被用于精确值比對,這些精确值可能是數字、時間、布爾或者那些 not_analyzed(不分詞)的字元串

全文檢索用match,其他非text字段比對用term.若想使用match精确比對可以在比對時為字段加上keyword

例:“balance.keyword”

GET /_search
{
    "query": {
        "term": {
            "user": {
                "value": "Kimchy",
                "boost": 1.0
            }
        }
    }
}
           

range 查詢

range 查詢找出那些落在指定區間内的數字或者時間:

{
    "range": {
        "age": {
            "gte":  20,
            "lt":   30
        }
    }
}
           

gt大于;gte大于等于;lt小于;lte小于等于

exists 查詢和 missing 查詢

exists 查詢和 missing 查詢被用于查找那些指定字段中有值 (exists) 或無值 (missing) 的文檔。這與SQL中的 IS_NULL (missing) 和 NOT IS_NULL (exists) 在本質上具有共性:

{
    "exists":   {
        "field":    "title"
    }
}
           

這些查詢經常用于某個字段有值的情況和某個字段缺值的情況。

3.aggregations聚合

聚合可以讓我們極其友善的實作對資料的統計、分析。例如:

什麼品牌的手機最受歡迎?

這些手機的平均價格、最高價格、最低價格?

這些手機每月的銷售情況如何?

實作這些統計功能的比資料庫的sql要友善的多,而且查詢速度非常快,可以實作實時搜尋效果。

聚合有四個關鍵字:Metric(名額)、Bucketing(桶)、Matrix(矩陣)、Pipeline(管道),在查詢請求體中以aggregations文法來定義聚合分析,也可簡寫成aggs

  • Metric(名額):名額分析類型,如計算最大值、最小值、平均值等(對桶内的文檔進行聚合分析的操作)
  • Bucket(桶):分桶類型,類似sql中的group by文法(滿足特定條件的文檔的集合)
  • Pipeline(管道):管道分析類型,基于上一級的聚合分析結果進行再分析
  • Matrix(矩陣):矩陣分析類型(聚合是一種面向數值型的聚合,用于計算一組文檔字段中的統計資訊)
##搜尋address中包含mill的所有人的年齡分布以及平均年齡
GET bank/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  },
  "aggs": {
    "ageAggs": {
      "terms": {	//查詢年齡分布資訊
        "field": "age",
        "size": 100
      }
    },
    "aggsAvg": {
      "avg": {
        "field": "age"
      }
    }
  }
}

##按照年齡聚合,并且求這些年齡段的這些人的平均薪資
GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {
        "ageAvgBalance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}

##查出所有年齡分布,并且求這些年齡段中男性的平均薪資和女性的平均薪資以及這個年齡段的總體平均薪資
GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "ageAggs": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {
        "genderAggs": {
          "terms": {
            "field": "gender.keyword",
            "size": 10
          },
          "aggs": {
            "balanceAvg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "ageBalanceAvg":{
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}
           

可在聚合每内部進行對聚合結果進行子聚合,文法與聚合相同

4.Mapping(映射)

Mapping是ES中的一個很重要的内容,它類似于傳統關系型資料中table的schema,用于定義一個索引(index)中的類型(type)的資料的結構。 在ES中,我們可以手動建立type(相當于table)和mapping(相關與schema),也可以采用預設建立方式。在預設配置下,ES可以根據插入的資料自動地建立type及其mapping。 mapping中主要包括字段名、字段資料類型和字段索引類型

為什麼類型概念被移除了?

上面,我們說索引和關系資料庫的庫是對等的的,類型和表是對等的。

這個觀點其實是不正确的,在關系型資料庫裡,表是互相獨立的,兩個不同表裡的同名列沒有關系,互不影響。

但在索引裡,所有類型的相同字段内部使用的是同一個lucene字段存儲。上例中,user類型和tweet類型的user_name是存儲在一個字段裡的,但這是有問題的,例如你希望同一個索引中deleted字段在一個類型裡是存儲日期值,在另外一個類型裡存儲布爾值。而且索引中,存儲僅有小部分字段相同或者全部字段都不相同的文檔,會導緻資料稀疏,影響Lucene有效壓縮資料的能力。

字段類型

Elasticsearch 支援如下簡單域類型:

字元串: string

整數 : byte, short, integer, long

浮點數: float, double

布爾型: boolean

日期: date

當你索引一個包含新域的文檔Elasticsearch 會使用動态映射 ,通過JSON中基本資料類型,嘗試猜測域類型,使用如下規則:

布爾型: true 或者 false—>boolean

整數: 123—>long

浮點數: 123.45—>double

字元串、有效日期: 2014-09-15—>date

字元串: foo bar—>string

如果通過引号( “123” )索引一個數字,它會被映射為 string 類型,而不是 long 。但是,如果我們設定了映射為 long ,那麼 Elasticsearch 會嘗試将這個字元串轉化為 long ,如果無法轉化,則抛出一個異常。

定義映射

## 儲存索引并建立映射規則
PUT /my_index
{
  "mappings": {
    "properties": {
      "age":{ "type": "integer"},
      "email":{ "type": "keyword"},
      "name":{ "type": "text"}     
    }
  }
           

為索引 gb 中類型 (tweet) 建立映射規則 7.0之後類型概念被移除

GET /gb/_mapping/tweet
{
   "gb": {
      "mappings": {
         "tweet": {
            "properties": {
               "date": {
                  "type": "date",
                  "format": "strict_date_optional_time||epoch_millis"
               },
               "name": { "type": "string"},
               "tweet": {"type": "string"},
               "user_id": {"type": "long"},
               "add_file":{				//為索引中添加新的字段設定映射時應使用index
               		"type": "long",
               		"index":false
               }
            }
         }
      }
   }
}
           

為原有的映射添加新的字段使用 /索引名/_mapping

PUT /my-index/_mapping
{
  "properties": {
    "employee-id": {
      "type": "keyword",
      "index": false
    }
  }
}
           

更新字段的映射

可以給一個存在的映射添加新的字段類型映射,但不能修改存在的字段類型映射。如果一個字段類型映射已經存在,那麼該字段類型映射可能已經被索引。如果你意圖修改這個字段類型映射,索引的資料可能會出錯,不能被正常的搜尋。(使用資料遷移解決)

資料遷移

GET bank/_mapping 檢視原有索引的映射

根據原有索引映射,建立一個新的索引newbank書寫正确的屬性類型映射

PUT /newbank
{
  "mappings": {
    "properties": {
      "account_number": {"type": "long"},
      "address": {"type": "text"},
      "age": {"type": "integer"},
      "balance": {"type": "long"},
      "city": {"type": "text"},
      "email": {"type": "keyword"},	//對email字段進行精确檢索設定
      "employer": {"type": "keyword"},
      "firstname": {"type": "text"},
      "gender": {"type": "keyword"},
      "lastname": {		//對lastname字段進行精确檢索和分詞比對
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "state": {"type": "keyword"}
    }
  }
}
           

若es版本小于7.0在資料遷移時需要在source屬性中加上type字段指定相應的類型即可

POST _reindex
{
  "source": {
    "index": "bank"
  },
  "dest": {
    "index": "newbank"
  }
}
           

六、ik分詞器

es自帶的分詞器全是基于英文的這裡我們要安裝可以進行中文的分詞器

分詞器安裝

下載下傳位址:https://github.com/medcl/elasticsearch-analysis-ik/releases 下載下傳與es版本對應的ik分詞器(不要點選tag去選版本下載下傳來的檔案少東西)

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

前面安裝es時我們講檔案挂載到了mydata下 這裡下載下傳解壓可以直接将檔案夾使用xftp拷貝到伺服器上

也可以使用下面的wget指令安裝ik分詞器

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

安裝完成需要使用指令修改ik的讀寫權限

chmod -R 777 ik/

檢查是否安裝成功

安裝後重新開機容器

docker restart elasticsearch

檢查分詞器是否安裝成功

docker exec -it 容器id /bin/bash 進入es的控制台

elasticsearch-plugin list 檢視所有已經安裝的插件

嘗試使用ik分詞器進行分詞(發現喬碧蘿新詞不能像預期的那樣分成一個次這是我們就需要擴充自定義詞庫)

POST _analyze
{
  "analyzer": "ik_max_word",
  "text":"一群嘴炮!"
}
           
進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

自定義擴充詞庫

場景:ik分詞器預設不能識别流行新詞,這是就需要自定義擴充詞庫

解決方法:

指定遠端詞庫向遠端詞庫擷取新的分詞庫,使用新的分詞庫進行分解單詞

**将最新詞庫放入nginx讓ik分詞器給nginx發送請求,nginx給我們傳回最新的詞庫 **

先安裝nginx 參考nginx基于docker環境搭建

在安裝好的nginx環境下的html檔案夾下建立es檔案夾與fenci.txt檔案 這就是我們擴充的自定義詞庫

mkdir es

vi fenci.txt

修改/mydata/elasticsearch/plugins/ik/config配置檔案

vi /mydata/elasticsearch/plugins/ik/config IKAnalyzer.cfg.xml

修改前的檔案

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

修改後的檔案

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

這裡遠端擴充字典的詞庫檔案fenci.txt存在我們的nginx中,以後若想添加分詞則在fenci.txt中加入即可

将嘴炮添加到分詞中再次進行分詞

POST _analyze
{
  "analyzer": "ik_smart",
  "text":"一群嘴炮!"
}
           
進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

七、整合ElasticSearch測試

SpringBoot預設支援兩種技術來和ES互動

  • Jest(預設不生效)

    需要導入jest的工具包依賴(io.searchbox.client.JestClient)

<!-- jestClient方式操作elasticsearch -->
        <dependency>
            <groupId>io.searchbox</groupId>
            <artifactId>jest</artifactId>
            <version>6.3.1</version>
        </dependency>
           

boot配置檔案

測試使用jest

@SpringBootTest
class BootSenior03ElasticsearchApplicationTests {

    @Autowired
    JestClient jestClient;

    @Test
    void contextLoads() throws IOException {
        //給es中索引一個文檔   /company/person/1
        Index index = new Index.Builder(new Employee(1, "張三", "CC", "老實人")).index("company").type("person").build();
        jestClient.execute(index);
    }

    @Test
    void contextLoads1() throws IOException {
        //從es中檢索描述字段為老實人的文檔   get/company/person/1
        String queryJson = "{\n" +
                "    \"query\" : {\n" +
                "        \"match_phrase\" : {\n" +
                "            \"description\" : \"老實人\"\n" +
                "        }\n" +
                "    }\n" +
                "}";
        Search search = new Search.Builder(queryJson).addIndex("company").addType("person").build();
        SearchResult result = jestClient.execute(search);
        System.out.println(result.getJsonString());
    }
}

           
  • SpringData 操作 ElasticSearch(注意版本)

    此處參考上文ElasticSearch中的版本比對說明

引入spring-boot-starter-data-elasticsearch

<!--Spring Data操作elasticsearch-->
       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
           

application.yml配置

spring.data.elasticsearch.clusterName=docker-cluster
spring.data.elasticsearch.clusterNodes=192.168.1.5:9300
           

springdata操作Elasticsearch的兩種方法

參考文檔

@Document(indexName = "company",type ="person" )
public class Employee {
    @JestId
    private Integer id;
    private String name;
    private String department;
    private String description;

           

1、ElasticsearchTemplate 操作es

2、編寫一個 ElasticsearchRepository 的子接口來操作ES;

public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
//CrudRepository中有很多可用的操作elasticsearch索引文檔的方法,若不滿足使用可以在此處重寫方法}
}
           
@SpringBootTest
class BootSenior03ElasticsearchApplicationTests {
    @Autowired
    EmployeeRepository employeeRepository;

    @Test
    void repositoryTest(){
        /*向索引中添加文檔*/
        Employee employee = new Employee(2, "李四", "SS", "海王");
        employeeRepository.save(employee);
        /*檢索文檔
        Optional<Employee> byId = employeeRepository.findById(1);
        System.out.println(byId.get().toString());*/
    }
}

           

八、ES操作–在java中的操作

使用9200:HTTP方式與ElasticSearch服務進行互動

ElasticSearch-Rest-Client:官方RestClient封裝了ES操作,API層次分明,上手簡單。

官方文檔:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html

springboot操作es

依賴:elasticsearch-rest-high-level-client

編寫配置:給容器中注入RestHighLevelClient

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

索引一個文檔

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

檢索一個文檔

進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

九、ES的使用場景(資料存儲在記憶體中)

9.1用作檢索

9.1.1商品的上架功能将商品資料存儲到es中

  • 分析es資料模型,并根據對應模型建立javabean(skuEsModel)

    若記憶體不夠用可采取分布式叢集,但記憶體比硬碟成本貴,所在存儲商品資訊到es存儲中應考慮存哪些資料應儲存,除了sku的基本資訊id,價格,品牌,銷量,分類,商品标題等常用來做查詢條件的字段,還應儲存商品規格;

  • 組裝skuEsModel(抽取的商品es模型)資料
    進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)
  • 将skuEsModel資料存儲到es中
    進階篇(102-125)ElasticSearch 檢索一、檢索概述二 、使用docker安裝Elasticsearch三、Elasticsearch中的幾個概念四、初步檢索五、進階檢索六、ik分詞器七、整合ElasticSearch測試八、ES操作–在java中的操作九、ES的使用場景(資料存儲在記憶體中)

9.1.2商品的全局檢索功能

  1. 用作日志分析(ELK)

繼續閱讀