日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

springCloud学习【4】之elasticsearch(1)

發(fā)布時(shí)間:2024/1/8 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 springCloud学习【4】之elasticsearch(1) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 一 初識(shí)elasticsearch
    • 1.1 認(rèn)識(shí)ES
    • 1.2 基知:倒排索引
    • 1.3 正向和倒排總結(jié)
    • 1.4 es基礎(chǔ)概念
  • 二 安裝elasticsearch
    • 2.1 部署部署單點(diǎn)es
      • 2.1.1 創(chuàng)建網(wǎng)絡(luò)
      • 2.1.2 下載鏡像
      • 2.1.3 加載鏡像
      • 2.1.4 運(yùn)行
      • 2.1.5 訪問
    • 2.2 部署kibana
      • 2.2.1 下載鏡像
      • 2.2.2 加載鏡像
      • 2.2.3 運(yùn)行kibana
      • 2.2.4 查看日志
      • 2.2.5 使用DevTools
    • 2.3 安裝IK分詞器
      • 2.3.1 在線安裝ik插件(較慢)
      • 2.3.2 離線安裝ik插件(推薦)
    • 2.4 拓展詞典
    • 2.5 停用詞詞典
    • 2.6 部署es集群【補(bǔ)充】
  • 三 索引庫操作
    • 3.1 mapping映射屬性
    • 3.2 創(chuàng)建索引庫和映射
    • 3.3 查詢索引庫
    • 3.4 修改索引庫
    • 3.5 刪除索引庫
    • 3.6 總結(jié)
  • 四 文檔操作
    • 4.1 新增文檔
    • 4.2 查詢文檔
    • 4.3 刪除文檔
    • 4.4 修改文檔
    • 4.5 總結(jié)
  • 五 RestAPI
    • 5.1 分析數(shù)據(jù)結(jié)構(gòu):apping映射分析
    • 5.2 初始化RestClient
    • 5.3 創(chuàng)建索引庫
    • 5.4 刪除索引庫
    • 5.5 判斷索引庫存在
    • 5.6 總結(jié)
  • 六 RestClient操作文檔
    • 6.1 新增文檔
    • 6.2 查詢文檔
    • 6.3 修改文檔
    • 6.4 刪除文檔
    • 6.5 批量導(dǎo)入文檔
    • 6.6 小結(jié)

一 初識(shí)elasticsearch

1.1 認(rèn)識(shí)ES

  • elasticsearch的作用
    • elasticsearch是一款非常強(qiáng)大的開源搜索引擎,具備非常多強(qiáng)大功能,可以幫助我們從海量數(shù)據(jù)中快速找到需要的內(nèi)容

  • ELK技術(shù)棧
    • elasticsearch結(jié)合kibana、Logstash、Beats,也就是elastic stack(ELK)。被廣泛應(yīng)用在日志數(shù)據(jù)分析、實(shí)時(shí)監(jiān)控等領(lǐng)域:
    • 而elasticsearch是elastic stack的核心,負(fù)責(zé)存儲(chǔ)、搜索、分析數(shù)據(jù)。

  • elasticsearch和lucene
    • elasticsearch底層是基于lucene來實(shí)現(xiàn)的。
    • Lucene是一個(gè)Java語言的搜索引擎類庫,是Apache公司的頂級(jí)項(xiàng)目,由DougCutting于1999年研發(fā)。

  • elasticsearch的發(fā)展歷史:
    • 2004年Shay Banon基于Lucene開發(fā)了Compass
    • 2010年Shay Banon 重寫了Compass,取名為Elasticsearch。

1.2 基知:倒排索引

  • 倒排索引的概念是基于MySQL這樣的正向索引而言的。
  • 正向索引:
    • 基于文檔id創(chuàng)建索引。查詢詞條時(shí)必須先找到文檔,而后判斷是否包含詞條

  • 逐行掃描,也就是全表掃描,隨著數(shù)據(jù)量增加,其查詢效率也會(huì)越來越低。當(dāng)數(shù)據(jù)量達(dá)到數(shù)百萬時(shí),就是一場災(zāi)難。
  • elasticsearch采用倒排索引
    • 文檔(document):用來搜索的數(shù)據(jù),每條數(shù)據(jù)就是一個(gè)文檔 例如:一個(gè)網(wǎng)頁、一個(gè)商品信息
    • 詞條(term):對(duì)文檔數(shù)據(jù)或用戶搜索數(shù)據(jù),利用某種算法分詞,得到的具備含義的詞語就是詞條。 例如:我是中國人,就可以分為:我、是、中國人、中國、國人這樣的幾個(gè)詞條
  • 創(chuàng)建倒排索引是對(duì)正向索引的一種特殊處理,流程如下:
  • 將每一個(gè)文檔的數(shù)據(jù)利用算法分詞,得到一個(gè)個(gè)詞條
  • 創(chuàng)建表,每行數(shù)據(jù)包括詞條、詞條所在文檔id、位置等信息
  • 因?yàn)樵~條唯一性,可以給詞條創(chuàng)建索引,例如hash表結(jié)構(gòu)索引
  • 倒排索引的搜索流程如下(以搜索"華為手機(jī)"為例):
    • 1)用戶輸入條件"華為手機(jī)"進(jìn)行搜索。
    • 2)對(duì)用戶輸入內(nèi)容分詞,得到詞條:華為、手機(jī)。
    • 3)拿著詞條在倒排索引中查找,可以得到包含詞條的文檔id:1、2、3。
    • 4)拿著文檔id到正向索引中查找具體文檔。
  • 雖然要先查詢倒排索引,再查詢倒排索引,但是無論是詞條、還是文檔id都建立了索引,查詢速度非???#xff01;無需全表掃描。

  • posting list
  • 倒排索引中包含兩部分內(nèi)容:
    • 詞條詞典(Term Dictionary):記錄所有詞條,以及詞條與倒排列表(Posting List)之間的關(guān)系,會(huì)給詞條創(chuàng)建索引,提高查詢和插入效率
    • 倒排列表(Posting List):記錄詞條所在的文檔id、詞條出現(xiàn)頻率 、詞條在文檔中的位置等信息
      • 文檔id:用于快速獲取文檔
      • 詞條頻率(TF):文檔在詞條出現(xiàn)的次數(shù),用于評(píng)分

1.3 正向和倒排總結(jié)

  • 正向索引是最傳統(tǒng)的,根據(jù)id索引的方式。但根據(jù)詞條查詢時(shí),必須先逐條獲取每個(gè)文檔,然后判斷文檔中是否包含所需要的詞條,是根據(jù)文檔找詞條的過程
  • 倒排索引則相反,是先找到用戶要搜索的詞條,根據(jù)詞條得到保護(hù)詞條的文檔的id,然后根據(jù)id獲取文檔。是根據(jù)詞條找文檔的過程。
  • 正向索引
    • 優(yōu)點(diǎn):
      • 可以給多個(gè)字段創(chuàng)建索引
      • 根據(jù)索引字段搜索、排序速度非常快
    • 缺點(diǎn):
      • 根據(jù)非索引字段,或者索引字段中的部分詞條查找時(shí),只能全表掃描。
  • 倒排索引
    • 優(yōu)點(diǎn):
      • 根據(jù)詞條搜索、模糊搜索時(shí),速度非???/li>
    • 缺點(diǎn):
      • 只能給詞條創(chuàng)建索引,而不是字段
      • 無法根據(jù)字段做排序

1.4 es基礎(chǔ)概念

  • 文檔和字段
    • elasticsearch是面向文檔(Document) 存儲(chǔ)的,可以是數(shù)據(jù)庫中的一條商品數(shù)據(jù),一個(gè)訂單信息。
    • 文檔數(shù)據(jù)會(huì)被序列化為json格式后存儲(chǔ)在elasticsearch中,而Json文檔中往往包含很多的字段(Field)

  • 索引和映射
    • 索引(Index),就是相同類型的文檔的集合。
    • 映射(mapping):索引中文檔的字段約束信息,類似表的結(jié)構(gòu)約束

  • **mysql與elasticsearch的概念對(duì)比:加粗樣式
MySQLElasticsearch說明
TableIndex索引(index),就是文檔的集合,類似數(shù)據(jù)庫的表(table)
RowDocument文檔(Document),就是一條條的數(shù)據(jù),類似數(shù)據(jù)庫中的行(Row),文檔都是JSON格式
ColumnField字段(Field),就是JSON文檔中的字段,類似數(shù)據(jù)庫中的列(Column)
SchemaMappingMapping(映射)是索引中文檔的約束,例如字段類型約束。類似數(shù)據(jù)庫的表結(jié)構(gòu)(Schema)
SQLDSLDSL是elasticsearch提供的JSON風(fēng)格的請(qǐng)求語句,用來操作elasticsearch,實(shí)現(xiàn)CRUD

  • 架構(gòu)
    • Mysql:擅長事務(wù)類型操作,可以確保數(shù)據(jù)的安全和一致性
    • Elasticsearch:擅長海量數(shù)據(jù)的搜索、分析、計(jì)算
  • 因此在企業(yè)中,往往是兩者結(jié)合使用:
    • 對(duì)安全性要求較高的寫操作,使用mysql實(shí)現(xiàn)
    • 對(duì)查詢性能要求較高的搜索需求,使用elasticsearch實(shí)現(xiàn)
    • 兩者再基于某種方式,實(shí)現(xiàn)數(shù)據(jù)的同步,保證一致性

二 安裝elasticsearch

2.1 部署部署單點(diǎn)es

2.1.1 創(chuàng)建網(wǎng)絡(luò)

  • 因?yàn)檫€需要部署kibana容器,因此需要讓es和kibana容器互聯(lián)。先創(chuàng)建一個(gè)網(wǎng)絡(luò):docker network create es-net

2.1.2 下載鏡像

  • 這里采用elasticsearch的7.12.1版本的鏡像,不建議pull。
  • Elasticsearch中文社區(qū)下載地址

    • 記得將壓縮包的名稱修改為es.tar

2.1.3 加載鏡像

[root@kongyue ~]# systemctl start docker [root@kongyue ~]# cd /tmp/ [root@kongyue tmp]# docker load -i es.tar 2653d992f4ef: Loading layer [==================================================>] 216.5MB/216.5MB 0ba8eff8aa04: Loading layer [==================================================>] 101.4MB/101.4MB 2a944434ad00: Loading layer [==================================================>] 314.9kB/314.9kB ade95a7611c0: Loading layer [==================================================>] 543.9MB/543.9MB 09a575a6e776: Loading layer [==================================================>] 26.62kB/26.62kB 498ae65924d7: Loading layer [==================================================>] 7.68kB/7.68kB 36b3f8db7aaa: Loading layer [==================================================>] 490.5kB/490.5kB Loaded image: elasticsearch:7.12.1

2.1.4 運(yùn)行

docker run -d \--name es \-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \-e "discovery.type=single-node" \-v es-data:/usr/share/elasticsearch/data \-v es-plugins:/usr/share/elasticsearch/plugins \--privileged \--network es-net \-p 9200:9200 \-p 9300:9300 \ elasticsearch:7.12.1

命令解釋:

  • -e "cluster.name=es-docker-cluster":設(shè)置集群名稱
  • -e "http.host=0.0.0.0":監(jiān)聽的地址,可以外網(wǎng)訪問
  • -e "ES_JAVA_OPTS=-Xms512m -Xmx512m":內(nèi)存大小
  • -e "discovery.type=single-node":非集群模式
  • -v es-data:/usr/share/elasticsearch/data:掛載邏輯卷,綁定es的數(shù)據(jù)目錄
  • -v es-logs:/usr/share/elasticsearch/logs:掛載邏輯卷,綁定es的日志目錄
  • -v es-plugins:/usr/share/elasticsearch/plugins:掛載邏輯卷,綁定es的插件目錄
  • --privileged:授予邏輯卷訪問權(quán)
  • --network es-net :加入一個(gè)名為es-net的網(wǎng)絡(luò)中
  • -p 9200:9200:端口映射配置
[root@kongyue tmp]# docker run -d \ > --name es \ > -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \ > -e "discovery.type=single-node" \ > -v es-data:/usr/share/elasticsearch/data \ > -v es-plugins:/usr/share/elasticsearch/plugins \ > --privileged \ > --network es-net \ > -p 9200:9200 \ > -p 9300:9300 \ > elasticsearch:7.12.1 f1f899239f106e6f0718b632383ed0401cb4b8e96772a7cb1e0d3c890862cfb6

2.1.5 訪問

  • 訪問:http://xxx.xxx.xxx.xxx:9200 即可看到elasticsearch的響應(yīng)結(jié)果:

2.2 部署kibana

2.2.1 下載鏡像

  • 官方地址Download Kibana
  • Elasticsearch中文社區(qū)下載地址
    • 記得將壓縮包的名稱修改為kibana.tar

2.2.2 加載鏡像

[root@kongyue tmp]# docker load -i kibana.tar d797e87ed4ce: Loading layer [==================================================>] 112.9MB/112.9MB 80ce41fc1f8a: Loading layer [==================================================>] 26.62kB/26.62kB 3345a8ffd0ea: Loading layer [==================================================>] 3.584kB/3.584kB d736a1702974: Loading layer [==================================================>] 20.34MB/20.34MB 570575469db2: Loading layer [==================================================>] 56.83kB/56.83kB 459d502a3562: Loading layer [==================================================>] 770.7MB/770.7MB f22a9f0649d0: Loading layer [==================================================>] 2.048kB/2.048kB 4b66f24ba0de: Loading layer [==================================================>] 4.096kB/4.096kB 0a50faa06266: Loading layer [==================================================>] 15.36kB/15.36kB 8a310ff91413: Loading layer [==================================================>] 4.096kB/4.096kB 5997553ddc84: Loading layer [==================================================>] 479.2kB/479.2kB f87dadd7c340: Loading layer [==================================================>] 309.8kB/309.8kB Loaded image: kibana:7.12.1

2.2.3 運(yùn)行kibana

  • kibana啟動(dòng)一般比較慢,需要多等待一會(huì)
[root@kongyue tmp]# docker run -d \ > --name kibana \ > -e ELASTICSEARCH_HOSTS=http://es:9200 \ > --network=es-net \ > -p 5601:5601 \ > kibana:7.12.1 d8ade4066ec86d48c10effe249b65c122b63bd6734b1708b941a221bc633be78
  • --network es-net :加入一個(gè)名為es-net的網(wǎng)絡(luò)中,與elasticsearch在同一個(gè)網(wǎng)絡(luò)中
  • -e ELASTICSEARCH_HOSTS=http://es:9200":設(shè)置elasticsearch的地址,因?yàn)閗ibana已經(jīng)與elasticsearch在一個(gè)網(wǎng)絡(luò),因此可以用容器名直接訪問elasticsearch
  • -p 5601:5601:端口映射配置

2.2.4 查看日志

  • 可以通過命令,查看運(yùn)行日志:docker logs -f kibana
  • 當(dāng)查看到下面的日志,說明成功:{"type":"log","@timestamp":"2023-03-24T05:05:05+00:00","tags":["info","http","server","Kibana"],"pid":7,"message":"http server running at http://0.0.0.0:5601"}

2.2.5 使用DevTools

  • 訪問http://xxx.xxx.xxx.xxx:5601,即可看到以下頁面,選擇Explore on my own
  • 選擇開發(fā)工具
  • 然后進(jìn)入以下界面
  • 界面中可以編寫DSL來操作elasticsearch。并且對(duì)DSL語句有自動(dòng)補(bǔ)全功能。

2.3 安裝IK分詞器

2.3.1 在線安裝ik插件(較慢)

# 進(jìn)入容器內(nèi)部 docker exec -it elasticsearch /bin/bash# 在線下載并安裝 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip#退出 exit #重啟容器 docker restart elasticsearch

2.3.2 離線安裝ik插件(推薦)

  • 查看數(shù)據(jù)卷目錄
    • 安裝插件需要知道elasticsearch的plugins目錄位置,而我們用了數(shù)據(jù)卷掛載,因此需要查看elasticsearch的數(shù)據(jù)卷目錄
    • 通過下面命令查看:docker volume inspect es-plugins
    • 顯示結(jié)果:[root@kongyue tmp]# docker volume inspect es-plugins [{"CreatedAt": "2023-03-24T12:51:40+08:00","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/es-plugins/_data","Name": "es-plugins","Options": null,"Scope": "local"} ]
      • 說明plugins目錄被掛載到了:/var/lib/docker/volumes/es-plugins/_data 這個(gè)目錄中。
  • 下載IK分詞器
    • Elasticsearch中文社區(qū)下載地址
  • 解壓縮分詞器安裝包
    • 把ik分詞器解壓縮,重命名為ik
  • 上傳到es容器的插件數(shù)據(jù)卷中
    • 將ik文件夾上傳到查詢出來的掛載目錄
  • 重啟容器
  • # 重啟容器 docker restart es # 查看es日志 docker logs -f es
  • 測試:
    • IK分詞器包含兩種模式:
      • ik_smart:最少切分
      • ik_max_word:最細(xì)切分
    GET /_analyze {"analyzer": "ik_max_word","text": "天生我才必有用,大可不必獨(dú)嘆息" } {"tokens" : [{"token" : "天生我才必有用","start_offset" : 0,"end_offset" : 7,"type" : "CN_WORD","position" : 0},{"token" : "天生我才","start_offset" : 0,"end_offset" : 4,"type" : "CN_WORD","position" : 1},{"token" : "天生","start_offset" : 0,"end_offset" : 2,"type" : "CN_WORD","position" : 2},{"token" : "我","start_offset" : 2,"end_offset" : 3,"type" : "CN_CHAR","position" : 3},{"token" : "才","start_offset" : 3,"end_offset" : 4,"type" : "CN_CHAR","position" : 4},{"token" : "必有用","start_offset" : 4,"end_offset" : 7,"type" : "CN_WORD","position" : 5},{"token" : "必有","start_offset" : 4,"end_offset" : 6,"type" : "CN_WORD","position" : 6},{"token" : "有用","start_offset" : 5,"end_offset" : 7,"type" : "CN_WORD","position" : 7},{"token" : "大可不必","start_offset" : 8,"end_offset" : 12,"type" : "CN_WORD","position" : 8},{"token" : "大可","start_offset" : 8,"end_offset" : 10,"type" : "CN_WORD","position" : 9},{"token" : "可不","start_offset" : 9,"end_offset" : 11,"type" : "CN_WORD","position" : 10},{"token" : "不必","start_offset" : 10,"end_offset" : 12,"type" : "CN_WORD","position" : 11},{"token" : "獨(dú)","start_offset" : 12,"end_offset" : 13,"type" : "CN_CHAR","position" : 12},{"token" : "嘆息","start_offset" : 13,"end_offset" : 15,"type" : "CN_WORD","position" : 13}] }

    2.4 拓展詞典

    • 隨著互聯(lián)網(wǎng)的發(fā)展,出現(xiàn)了很多新的詞語,在原有的詞匯列表中并不存在。所以我們的詞匯也需要不斷的更新,IK分詞器提供了擴(kuò)展詞匯的功能。
  • 打開IK分詞器config目錄:
  • 在IKAnalyzer.cfg.xml配置文件內(nèi)容添加:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties><comment>IK Analyzer 擴(kuò)展配置</comment><!--用戶可以在這里配置自己的擴(kuò)展字典 *** 添加擴(kuò)展詞典--><entry key="ext_dict">ext.dic</entry> </properties>
  • 新建一個(gè) ext.dic,可以參考config目錄下復(fù)制一個(gè)配置文件進(jìn)行修改
    • 注意當(dāng)前文件的編碼必須是 UTF-8 格式
  • emo 芭比Q了
  • 重啟elasticsearch
  • docker restart es
  • 測試效果:
  • GET /_analyze {"analyzer": "ik_max_word","text": "競爭太激烈,這次面試又芭比Q了,我真的很emo" } {"token" : "emo","start_offset" : 20,"end_offset" : 23,"type" : "ENGLISH","position" : 13 }

    2.5 停用詞詞典

    • 在互聯(lián)網(wǎng)項(xiàng)目中,在網(wǎng)絡(luò)間傳輸?shù)乃俣群芸?#xff0c;所以很多語言是不允許在網(wǎng)絡(luò)上傳遞的,如:關(guān)于宗教、政治等敏感詞語,那么我們在搜索時(shí)也應(yīng)該忽略當(dāng)前詞匯。
    • IK分詞器也提供了強(qiáng)大的停用詞功能,讓我們在索引時(shí)就直接忽略當(dāng)前的停用詞匯表中的內(nèi)容。
  • IKAnalyzer.cfg.xml配置文件內(nèi)容添加:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties><comment>IK Analyzer 擴(kuò)展配置</comment><!--用戶可以在這里配置自己的擴(kuò)展字典--><entry key="ext_dict">ext.dic</entry><!--用戶可以在這里配置自己的擴(kuò)展停止詞字典 *** 添加停用詞詞典--><entry key="ext_stopwords">stopword.dic</entry> </properties>
  • 在 stopword.dic 添加停用詞
    • 注意當(dāng)前文件的編碼必須是 UTF-8 格式
    草泥馬 特么的
  • 重啟elasticsearch# 重啟服務(wù) docker restart elasticsearch docker restart kibana
  • 測試效果GET /_analyze {"analyzer": "ik_max_word","text": "草泥馬,特么的,都是不文明網(wǎng)絡(luò)用語" } {"tokens" : [{"token" : "草","start_offset" : 0,"end_offset" : 1,"type" : "CN_CHAR","position" : 0},{"token" : "泥","start_offset" : 1,"end_offset" : 2,"type" : "CN_CHAR","position" : 1},{"token" : "馬","start_offset" : 2,"end_offset" : 3,"type" : "CN_CHAR","position" : 2},{"token" : "特","start_offset" : 4,"end_offset" : 5,"type" : "CN_CHAR","position" : 3},{"token" : "么","start_offset" : 5,"end_offset" : 6,"type" : "CN_CHAR","position" : 4},{"token" : "的","start_offset" : 6,"end_offset" : 7,"type" : "CN_CHAR","position" : 5},{"token" : "都是","start_offset" : 8,"end_offset" : 10,"type" : "CN_WORD","position" : 6},{"token" : "不文明","start_offset" : 10,"end_offset" : 13,"type" : "CN_WORD","position" : 7},{"token" : "不文","start_offset" : 10,"end_offset" : 12,"type" : "CN_WORD","position" : 8},{"token" : "文明","start_offset" : 11,"end_offset" : 13,"type" : "CN_WORD","position" : 9},{"token" : "網(wǎng)絡(luò)","start_offset" : 13,"end_offset" : 15,"type" : "CN_WORD","position" : 10},{"token" : "用語","start_offset" : 15,"end_offset" : 17,"type" : "CN_WORD","position" : 11}] }
  • 2.6 部署es集群【補(bǔ)充】

    • 部署es集群可以直接使用docker-compose來完成,不過要求你的Linux虛擬機(jī)至少有4G的內(nèi)存空間
  • 首先編寫一個(gè)docker-compose文件,內(nèi)容如下:version: '2.2' services:es01:image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1container_name: es01environment:- node.name=es01- cluster.name=es-docker-cluster- discovery.seed_hosts=es02,es03- cluster.initial_master_nodes=es01,es02,es03- bootstrap.memory_lock=true- "ES_JAVA_OPTS=-Xms512m -Xmx512m"ulimits:memlock:soft: -1hard: -1volumes:- data01:/usr/share/elasticsearch/dataports:- 9200:9200networks:- elastices02:image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1container_name: es02environment:- node.name=es02- cluster.name=es-docker-cluster- discovery.seed_hosts=es01,es03- cluster.initial_master_nodes=es01,es02,es03- bootstrap.memory_lock=true- "ES_JAVA_OPTS=-Xms512m -Xmx512m"ulimits:memlock:soft: -1hard: -1volumes:- data02:/usr/share/elasticsearch/datanetworks:- elastices03:image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1container_name: es03environment:- node.name=es03- cluster.name=es-docker-cluster- discovery.seed_hosts=es01,es02- cluster.initial_master_nodes=es01,es02,es03- bootstrap.memory_lock=true- "ES_JAVA_OPTS=-Xms512m -Xmx512m"ulimits:memlock:soft: -1hard: -1volumes:- data03:/usr/share/elasticsearch/datanetworks:- elasticvolumes:data01:driver: localdata02:driver: localdata03:driver: localnetworks:elastic:driver: bridge
  • Run docker-compose to bring up the cluster:docker-compose up
  • 三 索引庫操作

    • 索引庫就類似數(shù)據(jù)庫表,mapping映射就類似表的結(jié)構(gòu)。要向es中存儲(chǔ)數(shù)據(jù),必須先創(chuàng)建“庫”和“表”。
    • 使用統(tǒng)一使用Kibana編寫DSL的方式來演示

    3.1 mapping映射屬性

    • type:字段數(shù)據(jù)類型,常見的簡單類型有:
      • 字符串:text(可分詞的文本)、keyword(精確值,例如:品牌、國家、ip地址)
      • 數(shù)值:long、integer、short、byte、double、float、
      • 布爾:boolean
      • 日期:date
      • 對(duì)象:object
    • index:是否創(chuàng)建索引,默認(rèn)為true
    • analyzer:使用哪種分詞器
    • properties:該字段的子字段

    • 舉例:{"age": 21,"weight": 52.1,"isMarried": false,"info": "武神","email": "zy@itcast.cn","score": [99.1, 99.5, 98.9],"name": {"firstName": "云","lastName": "趙"} }
    • 對(duì)應(yīng)的每個(gè)字段映射(mapping):
      • age:類型為 integer;參與搜索,因此需要index為true;無需分詞器
      • weight:類型為float;參與搜索,因此需要index為true;無需分詞器
      • isMarried:類型為boolean;參與搜索,因此需要index為true;無需分詞器
      • info:類型為字符串,需要分詞,因此是text;參與搜索,因此需要index為true;分詞器可以用ik_smart
      • email:類型為字符串,但是不需要分詞,因此是keyword;不參與搜索,因此需要index為false;無需分詞器
      • score:雖然是數(shù)組,但是我們只看元素的類型,類型為float;參與搜索,因此需要index為true;無需分詞器
      • name:類型為object,需要定義多個(gè)子屬性
        • name.firstName;類型為字符串,但是不需要分詞,因此是keyword;參與搜索,因此需要index為true;無需分詞器
        • name.lastName;類型為字符串,但是不需要分詞,因此是keyword;參與搜索,因此需要index為true;無需分詞器

    3.2 創(chuàng)建索引庫和映射

    • 基本語法:
      • 請(qǐng)求方式:PUT
      • 請(qǐng)求路徑:/索引庫名,可以自定義
      • 請(qǐng)求參數(shù):mapping映射
    • 格式:PUT /索引庫名稱 {"mappings": {"properties": {"字段名":{"type": "text","analyzer": "ik_smart"},"字段名2":{"type": "keyword","index": "false"},"字段名3":{"properties": {"子字段": {"type": "keyword"}}}}} }
    • 舉例:PUT /test01 {"mappings": {"properties": {"info":{"type": "text","analyzer": "ik_smart"},"email":{"type": "keyword","index": "false"},"name":{"properties": {"firstName": {"type": "keyword"}}}}} }
    • 演示結(jié)果:{"acknowledged" : true,"shards_acknowledged" : true,"index" : "test01" }

    3.3 查詢索引庫

    • 基本語法

      • 請(qǐng)求方式:GET
      • 請(qǐng)求路徑:/索引庫名
      • 請(qǐng)求參數(shù):無
    • 格式

      GET /索引庫名
    • 演示:

    3.4 修改索引庫

    • 倒排索引結(jié)構(gòu)雖然不復(fù)雜,但是一旦數(shù)據(jù)結(jié)構(gòu)改變(比如改變了分詞器),就需要重新創(chuàng)建倒排索引,這簡直是災(zāi)難。因此索引庫一旦創(chuàng)建,無法修改mapping。
    • 雖然無法修改mapping中已有的字段,但是卻允許添加新的字段到mapping中,因?yàn)椴粫?huì)對(duì)倒排索引產(chǎn)生影響。
    • 語法說明PUT /索引庫名/_mapping {"properties": {"新字段名":{"type": "integer"}} }
    • 演示:

    3.5 刪除索引庫

    • 語法:
      • 請(qǐng)求方式:DELETE
      • 請(qǐng)求路徑:/索引庫名
      • 請(qǐng)求參數(shù):無
    • 格式:DELETE /索引庫名

    3.6 總結(jié)

    • 索引庫操作:
      • 創(chuàng)建索引庫:PUT /索引庫名
      • 查詢索引庫:GET /索引庫名
      • 刪除索引庫:DELETE /索引庫名
      • 添加字段:PUT /索引庫名/_mapping

    四 文檔操作

    4.1 新增文檔

    • 語法:POST /索引庫名/_doc/文檔id {"字段1": "值1","字段2": "值2","字段3": {"子屬性1": "值3","子屬性2": "值4"},// ... }
    • 演示:

    4.2 查詢文檔

    • 語法:GET /{索引庫名稱}/_doc/{id}
    • 通過kibana查看數(shù)據(jù):GET /heima/_doc/1
    • 演示:

    4.3 刪除文檔

    • 語法:DELETE /{索引庫名}/_doc/id值
    • 演示:

    4.4 修改文檔

    • 修改有兩種方式:
      • 全量修改:直接覆蓋原來的文檔
      • 增量修改:修改文檔中的部分字段

    • 全量修改
    • 全量修改是覆蓋原來的文檔,其本質(zhì)是:
      • 根據(jù)指定的id刪除文檔
      • 新增一個(gè)相同id的文檔
    • 注意:如果根據(jù)id刪除時(shí),id不存在,第二步的新增也會(huì)執(zhí)行,也就從修改變成了新增操作了。
    • 語法:PUT /{索引庫名}/_doc/文檔id {"字段1": "值1","字段2": "值2",// ... 略 }
    • 演示:

    • 增量修改
    • 增量修改是只修改指定id匹配的文檔中的部分字段。
    • 語法:POST /{索引庫名}/_update/文檔id {"doc": {"字段名": "新的值"} }
    • 演示:

    4.5 總結(jié)

    • 文檔操作:
      • 創(chuàng)建文檔:POST /{索引庫名}/_doc/文檔id { json文檔 }
      • 查詢文檔:GET /{索引庫名}/_doc/文檔id
      • 刪除文檔:DELETE /{索引庫名}/_doc/文檔id
      • 修改文檔:
        • 全量修改:PUT /{索引庫名}/_doc/文檔id { json文檔 }
        • 增量修改:POST /{索引庫名}/_update/文檔id { "doc": {字段}}

    五 RestAPI

    • ES官方提供了各種不同語言的客戶端,用來操作ES。這些客戶端的本質(zhì)就是組裝DSL語句,通過http請(qǐng)求發(fā)送給ES。官方文檔地址
    • 其中的Java Rest Client又包括兩種:
      • Java Low Level Rest Client
      • Java High Level Rest Client
    • 這里使用Java HighLevel Rest Client客戶端API

    5.1 分析數(shù)據(jù)結(jié)構(gòu):apping映射分析

    • 創(chuàng)建索引庫,最關(guān)鍵的是mapping映射,而mapping映射要考慮的信息包括:
      • 字段名
      • 字段數(shù)據(jù)類型
      • 是否參與搜索
      • 是否需要分詞
      • 如果分詞,分詞器是什么?
    • 其中:
      • 字段名、字段數(shù)據(jù)類型,可以參考數(shù)據(jù)表結(jié)構(gòu)的名稱和類型
      • 是否參與搜索要分析業(yè)務(wù)來判斷,例如圖片地址,就無需參與搜索
      • 是否分詞呢要看內(nèi)容,內(nèi)容如果是一個(gè)整體就無需分詞,反之則要分詞
      • 分詞器,我們可以統(tǒng)一使用ik_max_word

    • 幾個(gè)特殊字段說明:
      • location:地理坐標(biāo),里面包含精度、緯度
      • all:一個(gè)組合字段,其目的是將多字段的值 利用copy_to合并,提供給用戶搜索
    • 地理坐標(biāo)說明:
    • copy_to說明:

    5.2 初始化RestClient

    • 在elasticsearch提供的API中,與elasticsearch一切交互都封裝在一個(gè)名為RestHighLevelClient的類中,必須先完成這個(gè)對(duì)象的初始化,建立與elasticsearch的連接。
    • 步驟分為三步:
    • 引入es的RestHighLevelClient依賴:
    • <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency>
    • 因?yàn)镾pringBoot默認(rèn)的ES版本是7.6.2,所以我們需要覆蓋默認(rèn)的ES版本:
    • <properties><java.version>1.8</java.version><elasticsearch.version>7.12.1</elasticsearch.version> </properties>
    • 初始化RestHighLevelClient:
    • RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.150.101:9200") ));
    • 測試,創(chuàng)建一個(gè)測試類HotelIndexTest,然后將初始化的代碼編寫在@BeforeEach方法中:
    • public class HotelIndexTest {private RestHighLevelClient client;@BeforeEachvoid setUp() {this.client = new RestHighLevelClient(RestClient.builder(//xxx.xxx.xxx.xxx 虛擬主機(jī)的IPHttpHost.create("http://xxx.xxx.xxx.xxx:9200")));}@AfterEachvoid tearDown() throws IOException {this.client.close();} }

    5.3 創(chuàng)建索引庫

    • 代碼分為三步:
    • 創(chuàng)建Request對(duì)象。因?yàn)槭莿?chuàng)建索引庫的操作,因此Request是CreateIndexRequest。
    • 添加請(qǐng)求參數(shù),其實(shí)就是DSL的JSON參數(shù)部分。因?yàn)閖son字符串很長,這里是定義了靜態(tài)字符串常量MAPPING_TEMPLATE,讓代碼看起來更加優(yōu)雅。
    • 發(fā)送請(qǐng)求,client.indices()方法的返回值是IndicesClient類型,封裝了所有與索引庫操作有關(guān)的方法。
    • 演示
    //創(chuàng)建一個(gè)類,定義mapping映射的JSON字符串常量 class HotelConstants {public static final String MAPPING_TEMPLATE = "{\n" +" \"mappings\": {\n" +" \"properties\": {\n" +" \"id\": {\n" +" \"type\": \"keyword\"\n" +" },\n" +" \"name\":{\n" +" \"type\": \"text\",\n" +" \"analyzer\": \"ik_max_word\",\n" +" \"copy_to\": \"all\"\n" +" },\n" +" \"address\":{\n" +" \"type\": \"keyword\",\n" +" \"index\": false\n" +" },\n" +" \"price\":{\n" +" \"type\": \"integer\"\n" +" },\n" +" \"score\":{\n" +" \"type\": \"integer\"\n" +" },\n" +" \"brand\":{\n" +" \"type\": \"keyword\",\n" +" \"copy_to\": \"all\"\n" +" },\n" +" \"city\":{\n" +" \"type\": \"keyword\",\n" +" \"copy_to\": \"all\"\n" +" },\n" +" \"starName\":{\n" +" \"type\": \"keyword\"\n" +" },\n" +" \"business\":{\n" +" \"type\": \"keyword\"\n" +" },\n" +" \"location\":{\n" +" \"type\": \"geo_point\"\n" +" },\n" +" \"pic\":{\n" +" \"type\": \"keyword\",\n" +" \"index\": false\n" +" },\n" +" \"all\":{\n" +" \"type\": \"text\",\n" +" \"analyzer\": \"ik_max_word\"\n" +" }\n" +" }\n" +" }\n" +"}"; } //在hotel-demo中的HotelIndexTest測試類中,編寫單元測試,實(shí)現(xiàn)創(chuàng)建索引 @Test void createHotelIndex() throws IOException {// 1.創(chuàng)建Request對(duì)象CreateIndexRequest request = new CreateIndexRequest("hotel");// 2.準(zhǔn)備請(qǐng)求的參數(shù):DSL語句request.source(MAPPING_TEMPLATE, XContentType.JSON);// 3.發(fā)送請(qǐng)求client.indices().create(request, RequestOptions.DEFAULT); }

    5.4 刪除索引庫

    • 刪除索引庫的DSL語句非常簡單:DELETE /hotel
    • 與創(chuàng)建索引庫相比:
      • 請(qǐng)求方式從PUT變?yōu)镈ELTE
      • 請(qǐng)求路徑不變
      • 無請(qǐng)求參數(shù)
    • 所以代碼的差異,注意體現(xiàn)在Request對(duì)象上。依然是三步走:
    • 創(chuàng)建Request對(duì)象。這次是DeleteIndexRequest對(duì)象
    • 準(zhǔn)備參數(shù)。這里是無參
    • 發(fā)送請(qǐng)求。改用delete方法
    • 編寫單元測試,實(shí)現(xiàn)刪除索引:@Test void testDeleteHotelIndex() throws IOException {// 1.創(chuàng)建Request對(duì)象DeleteIndexRequest request = new DeleteIndexRequest("hotel");// 2.發(fā)送請(qǐng)求client.indices().delete(request, RequestOptions.DEFAULT); }

    5.5 判斷索引庫存在

    • 判斷索引庫是否存在,本質(zhì)就是查詢,對(duì)應(yīng)的DSL是:GET /hotel
    • 因此與刪除的Java代碼流程是類似的。依然是三步走:
    • 創(chuàng)建Request對(duì)象。這次是GetIndexRequest對(duì)象
    • 準(zhǔn)備參數(shù)。這里是無參
    • 發(fā)送請(qǐng)求。改用exists方法
    • @Test void testExistsHotelIndex() throws IOException {// 1.創(chuàng)建Request對(duì)象GetIndexRequest request = new GetIndexRequest("hotel");// 2.發(fā)送請(qǐng)求boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);// 3.輸出System.err.println(exists ? "索引庫已經(jīng)存在!" : "索引庫不存在!"); }

    5.6 總結(jié)

    • JavaRestClient操作elasticsearch的流程基本類似。核心是client.indices()方法來獲取索引庫的操作對(duì)象。
    • 索引庫操作的基本步驟:
      • 初始化RestHighLevelClient
      • 創(chuàng)建XxxIndexRequest。XXX是Create、Get、Delete
      • 準(zhǔn)備DSL( Create時(shí)需要,其它是無參)
      • 發(fā)送請(qǐng)求。調(diào)用RestHighLevelClient#indices().xxx()方法,xxx是create、exists、delete

    六 RestClient操作文檔

    • 為了與索引庫操作分離,需要增加加一個(gè)測試類:
      • 初始化RestHighLevelClient
      • 酒店數(shù)據(jù)在數(shù)據(jù)庫,需要利用IHotelService去查詢,所以注入這個(gè)接口
      @SpringBootTest public class HotelDocumentTest {@Autowiredprivate IHotelService hotelService;private RestHighLevelClient client;@BeforeEachvoid setUp() {this.client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.150.101:9200")));}@AfterEachvoid tearDown() throws IOException {this.client.close();} }

    6.1 新增文檔

  • 索引庫實(shí)體類
    • 數(shù)據(jù)庫實(shí)體類->索引庫實(shí)體類
    @Data @NoArgsConstructor public class HotelDoc {private Long id;private String name;private String address;private Integer price;private Integer score;private String brand;private String city;private String starName;private String business;private String location;private String pic;public HotelDoc(Hotel hotel) {this.id = hotel.getId();this.name = hotel.getName();this.address = hotel.getAddress();this.price = hotel.getPrice();this.score = hotel.getScore();this.brand = hotel.getBrand();this.city = hotel.getCity();this.starName = hotel.getStarName();this.business = hotel.getBusiness();this.location = hotel.getLatitude() + ", " + hotel.getLongitude();this.pic = hotel.getPic();} }
    • 導(dǎo)入酒店數(shù)據(jù),基本流程一致,但是需要考慮幾點(diǎn)變化:
      • 酒店數(shù)據(jù)來自于數(shù)據(jù)庫,需要先查詢出來,得到hotel對(duì)象
      • hotel對(duì)象需要轉(zhuǎn)為HotelDoc對(duì)象
      • HotelDoc需要序列化為json格式
    • 因此,代碼整體步驟如下:
    • 根據(jù)id查詢酒店數(shù)據(jù)Hotel
    • 將Hotel封裝為HotelDoc
    • 將HotelDoc序列化為JSON
    • 創(chuàng)建IndexRequest,指定索引庫名和id
    • 準(zhǔn)備請(qǐng)求參數(shù),也就是JSON文檔
    • 發(fā)送請(qǐng)求
    • @Test void testAddDocument() throws IOException {// 1.根據(jù)id查詢酒店數(shù)據(jù)Hotel hotel = hotelService.getById(61083L);// 2.轉(zhuǎn)換為文檔類型HotelDoc hotelDoc = new HotelDoc(hotel);// 3.將HotelDoc轉(zhuǎn)jsonString json = JSON.toJSONString(hotelDoc);// 1.準(zhǔn)備Request對(duì)象IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());// 2.準(zhǔn)備Json文檔request.source(json, XContentType.JSON);// 3.發(fā)送請(qǐng)求client.index(request, RequestOptions.DEFAULT); }
    • 測試運(yùn)行結(jié)果:

    6.2 查詢文檔

    • 詢的目的是得到結(jié)果,解析為HotelDoc,因此難點(diǎn)是結(jié)果的解析
    • 結(jié)果是一個(gè)JSON,其中文檔放在一個(gè)_source屬性中,因此解析就是拿到_source,反序列化為Java對(duì)象即可
    • 三步走:
    • 準(zhǔn)備Request對(duì)象。這次是查詢,所以是GetRequest
    • 發(fā)送請(qǐng)求,得到結(jié)果。因?yàn)槭遣樵?#xff0c;這里調(diào)用client.get()方法
    • 解析結(jié)果,就是對(duì)JSON做反序列化
    • 編寫單元測試:@Test void testGetDocumentById() throws IOException {// 1.準(zhǔn)備RequestGetRequest request = new GetRequest("hotel", "61082");// 2.發(fā)送請(qǐng)求,得到響應(yīng)GetResponse response = client.get(request, RequestOptions.DEFAULT);// 3.解析響應(yīng)結(jié)果String json = response.getSourceAsString();HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println(hotelDoc); }

    6.3 修改文檔

    • 在RestClient的API中,全量修改與新增的API完全一致,判斷依據(jù)是ID:

      • 如果新增時(shí),ID已經(jīng)存在,則修改
      • 如果新增時(shí),ID不存在,則新增
    • Upsert:如果文檔尚不存在,則可以使用以下upsert方法定義一些內(nèi)容,這些內(nèi)容將作為新文檔插入

      String jsonString = "{\"created\":\"2017-01-01\"}"; request.upsert(jsonString, XContentType.JSON);
    • 全量修改:

      @Testvoid testUpdateDocument() throws IOException {// 1.準(zhǔn)備RequestUpdateRequest request = new UpdateRequest("hotel", "61083");// 2.準(zhǔn)備請(qǐng)求參數(shù)UpdateRequest doc = request.doc("price", "952","starName", "四鉆");request.upsert(doc, XContentType.JSON);// 3.發(fā)送請(qǐng)求client.update(request, RequestOptions.DEFAULT);}


    • 增量修改/*** 增量修改* @throws IOException*/ @Test void testUpdateDocument2() throws IOException {// 1.準(zhǔn)備RequestUpdateRequest request = new UpdateRequest("hotel", "61083");// 2.準(zhǔn)備請(qǐng)求參數(shù)UpdateRequest doc = request.doc("price", "888","starName", "八鉆");// 3.發(fā)送請(qǐng)求client.update(request, RequestOptions.DEFAULT); }

    6.4 刪除文檔

    • 三步走:
    • 準(zhǔn)備Request對(duì)象,因?yàn)槭莿h除,這次是DeleteRequest對(duì)象。要指定索引庫名和id
    • 準(zhǔn)備參數(shù),無參
    • 發(fā)送請(qǐng)求。因?yàn)槭莿h除,所以是client.delete()方法
    • @Test void testDeleteDocument() throws IOException {// 1.準(zhǔn)備RequestDeleteRequest request = new DeleteRequest("hotel", "61083");// 2.發(fā)送請(qǐng)求client.delete(request, RequestOptions.DEFAULT); }

    6.5 批量導(dǎo)入文檔

    • 需求:利用BulkRequest批量將數(shù)據(jù)庫數(shù)據(jù)導(dǎo)入到索引庫中

    • 步驟如下:

      • 利用mybatis-plus查詢酒店數(shù)據(jù)
      • 將查詢到的酒店數(shù)據(jù)(Hotel)轉(zhuǎn)換為文檔類型數(shù)據(jù)(HotelDoc)
      • 利用JavaRestClient中的BulkRequest批處理,實(shí)現(xiàn)批量新增文檔
    • 批量處理BulkRequest,其本質(zhì)就是將多個(gè)普通的CRUD請(qǐng)求組合在一起發(fā)送。

      • 其中提供了一個(gè)add方法,用來添加其他請(qǐng)求:
    • 能添加的請(qǐng)求包括:

      • IndexRequest:新增
      • UpdateRequest:修改
      • DeleteRequest:刪除
    • Bulk中添加了多個(gè)IndexRequest——批量新增功能

    • 編寫單元測試

      @Test void testBulkRequest() throws IOException {// 批量查詢酒店數(shù)據(jù)List<Hotel> hotels = hotelService.list();// 1.創(chuàng)建RequestBulkRequest request = new BulkRequest();// 2.準(zhǔn)備參數(shù),添加多個(gè)新增的Requestfor (Hotel hotel : hotels) {// 2.1.轉(zhuǎn)換為文檔類型HotelDocHotelDoc hotelDoc = new HotelDoc(hotel);// 2.2.創(chuàng)建新增文檔的Request對(duì)象request.add(new IndexRequest("hotel").id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc), XContentType.JSON));}// 3.發(fā)送請(qǐng)求client.bulk(request, RequestOptions.DEFAULT); }
    • 測試運(yùn)行結(jié)果:

    • 查詢數(shù)據(jù)庫的數(shù)據(jù)量
    • 查詢索引庫的文檔數(shù)量

    6.6 小結(jié)

    • 文檔操作的基本步驟:
      • 初始化RestHighLevelClient
      • 創(chuàng)建XxxRequest。XXX:Index、Get、Update、Delete、Bulk
      • 準(zhǔn)備參數(shù)(Index、Update、Bulk時(shí)需要)
      • 發(fā)送請(qǐng)求。調(diào)用RestHighLevelClient#.xxx()方法,xxx:index、get、update、delete、bulk
      • 解析結(jié)果(Get時(shí)需要)

    總結(jié)

    以上是生活随笔為你收集整理的springCloud学习【4】之elasticsearch(1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。