中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

推廣普通話活動總結重慶seo優(yōu)化公司

推廣普通話活動總結,重慶seo優(yōu)化公司,杭州 建設網站首頁,wordpress可視化主題制作邁向光明之路,必定荊棘叢生。 文章目錄 一、Elasticsearch概述二、初識ES倒排索引1. 正向索引2. 倒排索引 三、ES環(huán)境搭建1. 安裝單機版ES2. 安裝Kibana3. 安裝ik分詞器3.1 在線安裝ik插件3.2.離線安裝ik插件(推薦方式)3.3 自定義詞典 四、ES…

在這里插入圖片描述

邁向光明之路,必定荊棘叢生。

文章目錄

  • 一、Elasticsearch概述
  • 二、初識ES倒排索引
    • 1. 正向索引
    • 2. 倒排索引
  • 三、ES環(huán)境搭建
    • 1. 安裝單機版ES
    • 2. 安裝Kibana
    • 3. 安裝ik分詞器
      • 3.1 在線安裝ik插件
      • 3.2.離線安裝ik插件(推薦方式)
      • 3.3 自定義詞典
  • 四、ES核心概念
  • 五、ES基本操作(DSL)
    • 1. DSL介紹
    • 2. 索引庫相關操作
      • 2.1 創(chuàng)建索引庫
      • 2.2 查看所有索引庫
      • 2.3 查看指定索引庫
      • 2.4 刪除索引庫
    • 3. 文檔相關操作
      • 3.1 創(chuàng)建文檔
      • 3.2 查詢文檔
      • 3.3 修改文檔
      • 3.4 修改指定字段的值
      • 3.5 刪除文檔
      • 3.6 批量操作
        • 3.6.1 批量創(chuàng)建文檔
        • 3.6.2 批量刪除文檔
      • 3.7 Mapping映射
        • 3.7.1 查看映射
        • 3.7.2 Mapping映射的常見屬性
        • 3.7.3 創(chuàng)建索引庫和映射
  • 六、ES高級查詢(DSL)
    • 1. 查詢所有(match_all)
    • 2. 匹配查詢(match)
    • 3. 多字段匹配(multi_match)
    • 4. 前綴匹配(prefix)
    • 5. 關鍵字精確查詢(term)
    • 6. 多個關鍵字精確查詢(terms)
    • 7. 范圍查詢(range)
    • 8 返回指定字段(_source)
    • 9. 組合查詢(bool)
      • 9.1 must(并且)
      • 9.2 should(或者)
      • 9.3 must_not(非)
      • 9.4 filter
    • 10. 聚合查詢(aggs)
      • 10.1 max
      • 10.2 min
      • 10.3 avg
      • 10.4 sum
      • 10.5 stats
      • 10.6 terms(分組)
    • 11. 分頁查詢(from、size)
    • 12. 高亮查詢(highlight)
    • 13. 近似查詢(fuzzy)
  • 七、Java操作ES
    • 1. API介紹
    • 2. 使用RestHighLevelClient操作ES
      • 2.1 環(huán)境準備
      • 2.2 索引庫相關操作
        • 2.2.1 創(chuàng)建索引庫
        • 2.2.2 獲取所引庫
        • 2.2.3 刪除索引庫
      • 2.3 文檔相關操作
        • 2.3.1 數(shù)據(jù)準備
        • 2.3.2 添加文檔
        • 2.3.3 修改文檔
        • 2.3.4 根據(jù)id查詢文檔
        • 2.3.5 刪除文檔
        • 2.3.6 批量新增
      • 2.4 高級查詢
        • 2.4.1 查詢所有文檔
        • 2.4.2 匹配查詢
        • 2.4.3 高亮查詢
        • 2.4.4 聚合查詢
    • 3. 使用Spring Data Elasticsearch 操作ES
      • 3.1 Spring Data概述
      • 3.2 Spring Data Elasticsearch 概述
      • 3.3 環(huán)境準備
      • 3.4 使用ElasticsearchRestTemplate操作ES
        • 3.4.1 添加文檔
        • 3.4.2 根據(jù)ID查詢文檔
        • 3.4.3 修改文檔
        • 3.4.4 刪除文檔
        • 3.4.5 查詢所有文檔
        • 3.4.6 高亮查詢
        • 3.4.7 分頁查詢
        • 3.4.8 聚合查詢
      • 3.5 使用ElasticsearchRepository接口操作ES

一、Elasticsearch概述


在這里插入圖片描述

Elasticsearch(簡稱ES)是一個分布式、RESTful 風格的搜索引擎、數(shù)據(jù)分析引擎。ES底層是基于Apache Lucene搜索引擎庫實現(xiàn)的,但是ES的目的是通過簡單的RESTful API來隱藏Lucene的復雜性,從而讓全文搜索變得簡單。ES可以提供實時的數(shù)據(jù)存儲和檢索能力,并且擁有很好的可擴展性。它可以擴展到上百臺服務器,處理PB級別的數(shù)據(jù)(海量數(shù)據(jù)—千萬級以上)。

ES被廣泛應用于各種場景,例如:搜索引擎、日志管理、電商推薦、監(jiān)控和報告等。其強大的搜索和分析能力使得數(shù)據(jù)的處理變得簡單、高效和可擴展。

官網地址:https://www.elastic.co/cn/elasticsearch/


數(shù)據(jù)庫搜索存在的問題:

1、常見數(shù)據(jù)庫特點:

  • MySQL:事務
  • Redis:內存/讀寫效率高
  • MongoDB:最接近關系型的nosql
  • Elasticsearch:分布式搜索引擎,提供了Restful接口,ES也可以看做分布式文檔數(shù)據(jù)庫(通過DSL語句操作ES)。

2、普通數(shù)據(jù)庫可以實現(xiàn)搜索,為什么還要用ES?

  • 海量數(shù)據(jù)搜索效率低(逐行掃描方式)
    • 解決方案:針對要搜索的字段建立索引、對數(shù)據(jù)庫進行分庫分表處理(查詢效率提升了,但是添加效率會受到影響)
  • 搜索數(shù)據(jù)不夠全面。例如MySQL模糊查詢:like %聯(lián)想電腦% (只能搜索包含聯(lián)想電腦的內容,沒有實現(xiàn)分詞效果)

在這里插入圖片描述在這里插入圖片描述


Lucene、ElasticSearch相關概述:

1、Lucene介紹:

  • Lucene是基于Java語言開發(fā)的搜索引擎類庫,是Apache基金會的頂級項目,由DougCutting于1999年研發(fā)。

  • 官網地址:https://lucene.apache.org/

  • 優(yōu)點:易擴展、高性能(基于倒排索引)。

  • 缺點:只限于Java語言開發(fā)、學習曲線陡峭、不支持水平擴展(搭集群)。


2、ElasticSearch介紹:

  • 2004年Shay Banon基于Lucene開發(fā)了Compass。

  • 2010年Shay Banon重寫了Compass,取名為ElasticSearch。

  • 官網地址:https://www.elastic.co/products/elasticsearch

  • 目前最新版本:7.17.9、8.8.2(本文以7.12.1為例)

  • 相比Lucene,ElasticSearch具備下列優(yōu)勢:

    • 支持分布式,可水平擴展。
    • 提供Restful接口,可被任何語言調用。

ElasticSearch小故事:

在這里插入圖片描述

多年前,一個剛結婚不久的失業(yè)開發(fā)者Shay Banon(謝巴農),由于妻子要去倫敦學廚師,他便跟著去了。在他找工作的過程中,為了給妻子構建一個食譜的搜索引擎,于是他開始使用Lucene進行嘗試。

直接基于Lucene工作會比較困難,所以Shay開始抽象Lucene代碼以便Java程序員可以在應用中添加搜索功能。他發(fā)布了他的第一個開源項目,叫做“Compass”。

后來Shay找到一份工作,這份工作處在高性能和內存數(shù)據(jù)網格的分布式環(huán)境中,因此高性能的、實時的、分布式的搜索引擎也是理所當然需要的。于是他決定閉門造車重寫Compass庫使其成為一個獨立的服務叫做ElasticSearch。

第一個公開版本出現(xiàn)在2010年2月,在那之后ElasticSearch已經成為Github上最受歡迎的項目之一,代碼貢獻者超過300人。一家主營Elasticsearch的公司就此成立(Elastic),他們一邊提供商業(yè)支持一邊開發(fā)新功能,不過Elasticsearch將永遠開源且對所有人可用。

而Shay的妻子依舊等待著她的食譜搜索引擎……


ES 與 Apache Solr 搜索引擎對比:

1、ES基本是開箱即用,非常簡單。Solr安裝略微復雜。

2、Solr 利用 Zookeeper 進行分布式管理,而 Elasticsearch 自身帶有分布式協(xié)調管理功能。

3、Solr 支持更多格式的數(shù)據(jù),比如JSON、XML、CSV,而 Elasticsearch 僅支持json文件格式。

4、Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高級功能多有第三方插件提供,例如圖形化界面需要kibana友好支撐。

5、Solr 查詢快,但更新索引時慢(即插入刪除慢),用于電商等查詢多的應用;

  • ES建立索引快(即查詢慢),即實時性查詢快,用于facebook新浪等搜索。
  • Solr 是傳統(tǒng)搜索應用的有力解決方案,但 Elasticsearch 更適用于新興的實時搜索應用。

6、Solr比較成熟,有一個更大,更成熟的用戶、開發(fā)和貢獻者社區(qū),而 Elasticsearch相對開發(fā)維護者較少,更新太快,學習使用成本較高。


目前比較知名的搜索引擎技術排名:https://db-engines.com/en/ranking/search+engine


二、初識ES倒排索引


ES基于倒排索引提高查詢效率。

1. 正向索引


正向索引:建立文檔id和詞之間的對應關系。

在這里插入圖片描述

在正向索引中,每個文檔都會維護一個關鍵詞列表,記錄了該文檔包含的所有關鍵詞。當用戶發(fā)起搜索時,搜索引擎會遍歷索引庫中的所有文檔,并檢查每個文檔的關鍵詞列表,找出匹配程度最高的文檔。

存在的問題:如果正向索引中的數(shù)據(jù)量較大,就需要遍歷所有文檔才能找到匹配的結果,效率比較低。為了提高搜索效率,搜索引擎通常使用倒排索引來加速搜索過程。

2. 倒排索引


倒排索引:也稱之為反向索引,建立單詞和文檔id之間的對應關系。即把文檔→單詞的形式變?yōu)?mark>單詞→文檔的形式。(借助于分詞器)

在這里插入圖片描述

倒排索引建立過程:先對數(shù)據(jù)(文檔)進行分詞,得到一個個的詞條,然后將詞條與文檔id的對應關系保存起來。


那有了ES以后就不需要數(shù)據(jù)庫了嘛?

  • ES主要實現(xiàn)數(shù)據(jù)的搜索,并且ES還不支持事務,因此要保證數(shù)據(jù)一致性,還需要結合關系型數(shù)據(jù)庫使用。

在這里插入圖片描述

三、ES環(huán)境搭建


基于Docker安裝單機版ES。(ES版本為7.12.1)

1. 安裝單機版ES


1、創(chuàng)建Docker網絡(也就是一個標識,創(chuàng)建網絡的目的是讓es和kibana容器互聯(lián))

# 創(chuàng)建一個網絡
docker network create es-net#查看docker本機的網絡
docker network  ls #刪除網絡
# docker network rm es-net

在這里插入圖片描述


2、下載elasticsearch鏡像。(這個鏡像體積非常大,接近1個G)

docker pull elasticsearch:7.12.1

在這里插入圖片描述

下載成功后,別忘了導出鏡像,方便以后使用。

docker save -o es.tar elasticsearch:7.12.1 

3、啟動es容器(單機版es)

在這里插入圖片描述

docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
-e "discovery.type=single-node" \
-e TZ=Asia/Shanghai \
-v es-data:/usr/share/elasticsearch/data \
-v es-plugins:/usr/share/elasticsearch/plugins \
--network es-net \
--privileged \
--restart=always \
-d elasticsearch:7.12.1 
  • -e "cluster.name=es-docker-cluster":設置集群名稱。
  • -e "http.host=0.0.0.0":監(jiān)聽的地址,可以外網訪問。
  • -e "ES_JAVA_OPTS=-Xms512m -Xmx512m":設置容器內存大小。
  • -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:授予數(shù)據(jù)卷訪問權。
  • --network es-net :加入一個名為es-net的網絡中。
  • -p 9200:9200:端口映射配置, 9200是es與外部機器通訊的端口,9300是es集群節(jié)點之間通訊的端口。

4、瀏覽器測試訪問:http://192.168.150.123:9200/

在這里插入圖片描述


2. 安裝Kibana


Kibana是一個開源的數(shù)據(jù)分析可視化平臺,主要和ElasticSearch搭配使用。

可以對ES索引庫中的數(shù)據(jù)進行可視化(柱狀圖、餅狀圖、散點圖等)的數(shù)據(jù)展示,在Kibana中也提供了開發(fā)者工具(devtools),我們可以直接編寫DSL腳本請求ES的restful接口操作ES。

DSL(Domain Specific Language)領域專用語言,Elasticsearch提供了基于JSON的DSL來定義查詢。

Kibana是ES的可視化工具,幫助用戶實時分析和數(shù)據(jù)可視化,通過界面可以更方便學習ES。安裝Kibana時要與ES版本保持一致。

1、下載鏡像(與ES版本保持一致)

docker pull kibana:7.12.1

在這里插入圖片描述


2、啟動kibana容器

docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://elasticsearch:9200 \
--network=es-net \
-p 5601:5601  \
kibana:7.12.1
  • --network es-net :加入一個名為es-net的網絡中,與elasticsearch在同一個網絡中。
  • -e ELASTICSEARCH_HOSTS=http://es容器名:9200":設置elasticsearch的訪問地址,因為kibana已經與elasticsearch容器在同一個網絡,因此可以用容器名直接訪問elasticsearch。
  • -p 5601:5601:kibana容器外部訪問端口。

kibana啟動一般比較慢,需要多等待一會,可以通過命令查看是否啟動成功:

docker logs -f kibana

在這里插入圖片描述


3、瀏覽器測試訪問:http://192.168.150.123:5601/(點擊Explore on my own:獨自探索)

在這里插入圖片描述

在這里插入圖片描述


DevTools:在這個界面中可以編寫DSL(DSL是elasticsearch提供的JSON風格的請求語句,用來操作elasticsearch,實現(xiàn)CRUD)。并且對DSL語句有自動補全功能。
在這里插入圖片描述

示例:使用默認的標準分詞器(StandardAnalyzer),按詞切分,對中文不太友好。

# 使用默認的標準分詞器分詞
GET /_analyze
{"analyzer":"standard","text":"小米手機"
}

在這里插入圖片描述


3. 安裝ik分詞器


IK分詞器:一款開源的中文分詞器。項目地址:https://github.com/medcl/elasticsearch-analysis-ik

3.1 在線安裝ik插件


在這里插入圖片描述

# 進入es容器內部
docker exec -it elasticsearch /bin/bash# 在線下載ik分詞器插件并安裝
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip#退出容器
exit#重啟es容器
docker restart elasticsearch

3.2.離線安裝ik插件(推薦方式)


1、下載ik分詞器插件:https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip

在這里插入圖片描述

然后將文件解壓縮,修改文件夾名為:ik

在這里插入圖片描述


2、查看數(shù)據(jù)卷目錄

安裝插件需要知道es的plugins目錄位置,而我們在啟動容器時配置了掛載數(shù)據(jù)卷,所以通過下面命令查看即可:

# 查看es-plugins數(shù)據(jù)卷的詳細信息
docker volume inspect es-plugins

顯示結果:

說明plugins目錄被掛載到了:/var/lib/docker/volumes/es-plugins/_data 這個目錄。


3、將ik分詞器上傳到es容器的插件數(shù)據(jù)卷中: /var/lib/docker/volumes/es-plugins/_data
在這里插入圖片描述

在這里插入圖片描述


4、重啟容器

# 4、重啟容器
docker restart elasticsearch

5、測試ik分詞器:

IK分詞器提供了兩種分詞算法:

  • ik_smart:粗粒度分詞,分出的詞比較少。
  • ik_max_word:細粒度分詞,分出的詞比較多。

示例1:測試ik分詞器ik_max_word細粒度分詞

GET /_analyze
{"text": "中華人民共和國","analyzer": "ik_max_word"
}

執(zhí)行結果:

{"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" : 1,"end_offset" : 3,"type" : "CN_WORD","position" : 3},{"token" : "人民共和國","start_offset" : 2,"end_offset" : 7,"type" : "CN_WORD","position" : 4},{"token" : "人民","start_offset" : 2,"end_offset" : 4,"type" : "CN_WORD","position" : 5},{"token" : "共和國","start_offset" : 4,"end_offset" : 7,"type" : "CN_WORD","position" : 6},{"token" : "共和","start_offset" : 4,"end_offset" : 6,"type" : "CN_WORD","position" : 7},{"token" : "國","start_offset" : 6,"end_offset" : 7,"type" : "CN_CHAR","position" : 8}]
}

示例2:測試ik分詞器ik_smart粗粒度分詞

GET /_analyze
{"text": "中華人民共和國","analyzer": "ik_smart"
}

執(zhí)行結果:

{"tokens" : [{"token" : "中華人民共和國","start_offset" : 0,"end_offset" : 7,"type" : "CN_WORD","position" : 0}]
}

3.3 自定義詞典


IK分詞器之所以可以對中文進行合理的分詞,是因為在IK分詞器中提供了一個中文詞典(extra_main.dic),在這個詞典中定義了很多的詞。

在這里插入圖片描述在這里插入圖片描述

但是IK分詞器并不能把所有的詞全部考慮進去,比如網絡熱詞:內卷、躺平、奧利給等。

因此為了滿足開發(fā)的一些特殊化的需求,此時就需要自定義詞典,可以自定義兩類詞典:

  • 擴展詞詞典:定義自定義的詞

  • 停用詞詞典:定義不希望出現(xiàn)的詞

操作如下:

1、在/var/lib/docker/volumes/es-plugins/_data/ik/config目錄下創(chuàng)建一個ext.dic文件

# 創(chuàng)建自定義詞
cat << EOF > ext.dic
奧利給
笑不活
EOF

在這里插入圖片描述

2、修改IKAnalyzer.cfg.xml文件配置:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties><comment>IK Analyzer 擴展配置</comment><!--用戶可以在這里配置自己的擴展字典 --><entry key="ext_dict">ext.dic</entry><!--用戶可以在這里配置自己的擴展停止詞字典--><entry key="ext_stopwords">stopword.dic</entry><!--用戶可以在這里配置遠程擴展字典 --><!-- <entry key="remote_ext_dict">words_location</entry> --><!--用戶可以在這里配置遠程擴展停止詞字典--><!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

在這里插入圖片描述

3、重啟es容器

docker restart elasticsearch

4、測試:

GET /_analyze
{"analyzer":"ik_max_word","text":"加油奧利給"
}

執(zhí)行結果:

在這里插入圖片描述

ok,擴展詞典已經配置成功了。


四、ES核心概念


ES和關系型數(shù)據(jù)庫相關概念對比:

MySQLElasticsearch說明
DatabaseIndex索引庫,類似mysql中的數(shù)據(jù)庫
TableType類型,就是文檔的集合,類似數(shù)據(jù)庫的表(table)
RowDocument文檔(Document),就是一條條的數(shù)據(jù),類似數(shù)據(jù)庫中的行(Row),文檔都是JSON格式
ColumnField字段(Field),就是JSON文檔中的字段,類似數(shù)據(jù)庫中的列(Column)
SchemaMappingMapping(映射)是索引中文檔的約束,例如字段類型約束。類似數(shù)據(jù)庫的表結構(Schema)
SQLDSLDSL是elasticsearch提供的JSON風格的請求語句,用來操作elasticsearch,實現(xiàn)CRUD

在這里插入圖片描述

Elasticsearch是面向文檔型數(shù)據(jù)庫,一條數(shù)據(jù)在這里就是一個文檔,用JSON作為文檔序列化的格式,比如下面這條用戶數(shù)據(jù):

{"name" :     "John","sex" :      "Male","age" :      25,"birthDate": "1990/05/01","about" :    "I love to go rock climbing","interests": [ "sports", "music" ]
}

在一個索引庫中,你可以定義一種或多種類型(文檔集合)。

一個類型(Type)是索引的一個邏輯上的分類或分區(qū),用于對文檔進行組織和分類。每個索引可以包含多個類型,而每個類型又可以包含多個文檔。類型的語義完全由你來定義,它可以代表不同的實體、數(shù)據(jù)類型或者業(yè)務邏輯。例如,如果你有一個名為 “products” 的索引,你可以定義不同的類型來表示不同種類的產品,如"electronics"、 “clothing”、"books"等。

通常,會為具有一組共同字段的文檔定義一個類型。

不同版本的ES,類型會有一些變化:

版本Type
5.x支持多種type
6.x只能有一種type
7.x默認不再支持自定義索引類型(默認類型為:_doc)

五、ES基本操作(DSL)


1. DSL介紹


DSL(Domain Specific Language):領域專用語言,Elasticsearch提供了基于JSON的DSL來定義查詢。

文檔地址:https://www.elastic.co/guide/en/elasticsearch/reference/7.12/query-dsl.html

在這里插入圖片描述


2. 索引庫相關操作


2.1 創(chuàng)建索引庫


語法: PUT /{索引名稱}

PUT /my_index執(zhí)行結果:
{"acknowledged" : true,"shards_acknowledged" : true,"index" : "my_index"
}

在這里插入圖片描述


2.2 查看所有索引庫


語法: GET /_cat/indices?v
在這里插入圖片描述


2.3 查看指定索引庫


語法: GET /{索引名稱}

GET /my_index執(zhí)行結果:
{"my_index" : {"aliases" : { },"mappings" : { },"settings" : {"index" : {"creation_date" : "1633499968211","number_of_shards" : "1","number_of_replicas" : "1","uuid" : "bclHUdHrS4W80qxnj3NP0A","version" : {"created" : "7080099"},"provided_name" : "my_index"}}}
}

在這里插入圖片描述

lasticsearch在默認情況下為每個索引創(chuàng)建了兩個分片(一個主,一個備份),可以在創(chuàng)建索引庫時指定分片個數(shù)。


2.4 刪除索引庫


語法: DELETE /{索引名稱}

DELETE /my_index執(zhí)行結果:
{"acknowledged" : true
}

在這里插入圖片描述


小節(jié):

  • 創(chuàng)建索引庫:PUT /索引庫名
  • 查詢索引庫:GET /索引庫名
  • 刪除索引庫:DELETE /索引庫名

3. 文檔相關操作


3.1 創(chuàng)建文檔


語法格式如下:

PUT /{索引名稱}/類型/{id}
{jsonbody
}

在ES7以后的版本中,關于類型使用默認的值:_doc

#創(chuàng)建文檔
PUT /my_index/_doc/1
{"title": "小米手機","category": "小米","images": "http://www.gulixueyuan.com/xm.jpg","price": 3999
}返回結果:
{"_index" : "my_index","_type" : "_doc","_id" : "1","_version" : 1,"result" : "created","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1
}

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MghBptiu-1690304845291)(assets/image-20230719180214808.png)]


3.2 查詢文檔


① 根據(jù)id查詢索引庫下的文檔:GET /{索引名稱}/{類型}/{id}

# 查詢id為1的文檔
GET /my_index/_doc/1返回結果:
{"_index" : "my_index","_type" : "_doc","_id" : "1","_version" : 1,"_seq_no" : 0,"_primary_term" : 1,"found" : true,"_source" : {"title" : "小米手機","category" : "小米","images" : "http://www.gulixueyuan.com/xm.jpg","price" : 3999}
}

在這里插入圖片描述


② 查索引庫下的全部文檔:

GET /{索引庫名}/_search
{"query":{"match_all":{}}
}

在這里插入圖片描述


3.3 修改文檔


語法格式如下:

PUT /{索引名稱}/{類型}/{id}
{jsonbody
}
PUT /my_index/_doc/1
{"title": "華為手機","category": "華為","images": "http://www.gulixueyuan.com/xm.jpg"
}

在這里插入圖片描述

注意:修改文檔是先根據(jù)id把文檔刪除掉,然后重新添加文檔


3.4 修改指定字段的值


語法格式如下: (注:這種更新只能使用post方式)

POST /{索引名稱}/_update/{docId}
{"doc": {"屬性": "值"}
}

示例:修改文檔id為1的商品價格

POST /my_index/_update/1
{"doc": {"price": 4500}
}

在這里插入圖片描述


3.5 刪除文檔


語法: DELETE /{索引名稱}/{類型}/{id}

# 創(chuàng)建文檔
PUT  /my_index/_doc/2
{"title": "黑莓手機","category": "黑莓","images": "http://www.gulixueyuan.com/xm.jpg"
}# 刪除id為2的文檔
DELETE /my_index/_doc/2

在這里插入圖片描述


3.6 批量操作


通用語法:

POST
{"actionName":{"_index":"indexName", "_type":"typeName","_id":"id"}} 
{"field1":"value1", "field2":"value2"} 

actionName可以有CREATE、DELETE(批量添加or批量刪除)等。

3.6.1 批量創(chuàng)建文檔


POST _bulk
{"create":{"_index":"my_index","_id":2}}
{"id":2,"title":"華為手機","category":"華為","images":"http://www.gulixueyuan.com/xm.jpg","price":5500}
{"create":{"_index":"my_index","_id":3}}
{"id":3,"title":"VIVO手機","category":"vivo","images":"http://www.gulixueyuan.com/xm.jpg","price":3600}

3.6.2 批量刪除文檔


POST _bulk
{"delete":{"_index":"my_index","_id":2}}
{"delete":{"_index":"my_index","_id":3}}

小節(jié):

  • 創(chuàng)建文檔:POST /{索引庫名}/_doc/文檔id { jsonbody}
  • 查詢文檔:GET /{索引庫名}/_doc/文檔id
  • 刪除文檔:DELETE /{索引庫名}/_doc/文檔id
  • 修改文檔:
    • 全量修改:PUT /{索引庫名}/_doc/文檔id { jsonbody }
    • 增量修改(修改指定字段的值):POST /{索引庫名}/_update/文檔id { “doc”: {字段}}
  • 批量創(chuàng)建、刪除文檔

3.7 Mapping映射

在ES中,Mapping映射是用來定義索引庫中文檔的結構和字段類型。它類似于關系型數(shù)據(jù)庫中的表結構定義,可以設置每個字段的數(shù)據(jù)類型、分詞器、索引選項等。(Mapping映射更接近于定義表結構而不是整個數(shù)據(jù)庫結構)

在ES中可以不用先定義Mapping映射(即關系型數(shù)據(jù)庫的表、字段等),如果插入文檔時沒有事先定義Mapping映射,它會根據(jù)文檔字段的值自動推斷出字段的類型,并生成相應的映射。


3.7.1 查看映射


語法:GET /{索引庫名稱}/_mapping

GET /my_index/_mapping執(zhí)行結果:
{"my_index" : {"mappings" : {"properties" : {      "category" : {     //字段名稱"type" : "text", //字段類型},"id" : {"type" : "long"},"images" : {"type" : "text",},"price" : {"type" : "long"}}}}
}

3.7.2 Mapping映射的常見屬性


mapping是對索引庫中文檔的約束,mapping的常見屬性有:

  • type:用于指定字段數(shù)據(jù)類型,常見的簡單類型有:
    • 字符串:text(可分詞的文本)、keyword(精確值, 例如:品牌、國家、ip地址,keyword不能分詞)
    • 數(shù)值:long、integer、short、byte、double、float、…
    • 布爾:boolean
    • 日期:date
    • 對象:object
  • index:是否為字段創(chuàng)建索引(倒排索引),默認為true
  • analyzer:為指定字段配置分詞器
  • search_analyzer:配置該字段在搜索的時候所使用的分詞器(如果沒有指定該分詞器,那么搜索的時候使用analyzer所指定的分詞器)
  • properties:該字段的子字段

例如下面的json文檔:

{"title": "海爾冰箱","category": "海爾","images": "http://www.haier.com/bx.jpg","price": 1999
}

對應的每個字段映射(mapping):

1、title:字符串類型(text,可以分詞),需要索引(建立倒排索引提高查詢效率)

2、category:字符串類型(keyword), 需要索引

3、images:字符串類型(keyword) , 不需要索引 (該字段只用于存儲數(shù)據(jù),不需要進行搜索)

4、price:integer類型, 需要索引


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


靜態(tài)映射:就是可以事先定義好的映射,即手動配置映射,包含文檔的各個字段類型、分詞器等屬性。

在Elasticsearch中,一旦索引創(chuàng)建后,字段的映射是固定的,默認情況下是不可更改的。(注意:重新創(chuàng)建索引會數(shù)據(jù)丟失)

創(chuàng)建索引和映射語法如下:

PUT /索引庫名稱
{"mappings": {"properties": {"字段名":{"type": "text","analyzer": "ik_smart"},"字段名2":{"type": "keyword","index": "false"},"字段名3":{"properties": {"子字段": {"type": "keyword"}}},// ...略}}
}

示例:創(chuàng)建索引庫并配置字段映射

#創(chuàng)建索引庫,并同時指定映射關系和分詞器等屬性
PUT /my_index1
{"mappings": {  // 配置映射關系"properties": { // 配置文檔的字段"id":{"type": "long","index": true},"title": {"type": "text","index": true,  // 建立索引"analyzer": "ik_max_word", //建立索引使用的分詞器"search_analyzer": "ik_smart" },"category": {"type": "keyword","index": true},"images": {"type": "keyword","index": false},"price": {"type": "integer","index": true}}}
}返回結果:
{"acknowledged" : true,"shards_acknowledged" : true,"index" : "my_index"
}

在這里插入圖片描述

查看索引庫:
在這里插入圖片描述

小節(jié):

  • 查看映射:GET /索引庫名/_mapping
  • 創(chuàng)建索引并指定映射(定義表結構):PUT /索引庫名{mappings->properties->filed}

六、ES高級查詢(DSL)


DSL查詢文檔:https://www.elastic.co/guide/en/elasticsearch/reference/7.12/query-dsl.html

在這里插入圖片描述

準備數(shù)據(jù):

# 創(chuàng)建索引庫,并配置mapping映射
PUT /product
{"mappings": {"properties": {"id":{"type": "long","index": true},"title": {"type": "text","index": true,"analyzer": "ik_max_word","search_analyzer": "ik_smart"},"category": {"type": "keyword","index": true},"images": {"type": "keyword","index": false},"price": {"type": "integer","index": true}}}
}# 批量插入文檔
POST _bulk
{"create":{"_index":"product","_id":1}}
{"id":1,"title":"華為筆記本電腦","category":"華為","images":"http://www.huawei.com/dn.jpg","price":5388}
{"create":{"_index":"product","_id":2}}
{"id":2,"title":"華為手機","category":"華為","images":"http://www.huawei.com/sj.jpg","price":5500}
{"create":{"_index":"product","_id":3}}
{"id":3,"title":"VIVO手機","category":"vivo","images":"http://www.vivo.com/sj.jpg","price":3600}

在這里插入圖片描述


1. 查詢所有(match_all)


match_all :表示查詢所有文檔,一般測試用。(無條件查詢,類似 select * from table)

GET /product/_search
{"query": {"match_all": {}}
}

加粗樣式


2. 匹配查詢(match)


match:它可以根據(jù)指定的字段和搜索詞進行匹配查詢。(單字段)

match查詢會對搜索的關鍵詞進行分詞處理,然后將各個詞條從對應的倒排索引表中進行匹配。

match查詢語法如下:

GET /{索引名稱}/_search
{"query": {"match": {"FIELD": "TEXT"}}
}

示例:全文檢索title字段

GET /product/_search
{"query": {"match": {"title": "華為智能手機"   # 會對搜索的關鍵字進行分詞,然后將各個詞條從對應的倒排索引表中進行搜索}}
}

對搜索關鍵字進行分詞:華為,智能手機,智能,能手,手機。然后根據(jù)字段title的倒排索引表中進行匹配。
在這里插入圖片描述


3. 多字段匹配(multi_match)


multi_match多字段匹配語法如下:

GET /{索引名稱}/_search
{"query": {"multi_match": {"query": "TEXT","fields": ["FIELD1", " FIELD12"]}}
}

示例:

GET /product/_search
{"query": {"multi_match": {"query": "華為智能手機","fields": ["title","category"]}}
}

在這里插入圖片描述


4. 前綴匹配(prefix)


prefix前綴匹配語法如下:

GET /{索引名稱}/_search
{"query": {"prefix": {"FIELD": {"value": "指定前綴"}}}
}

示例:查詢字段title中以vivo開頭的文檔:(類似mysql中的 like ‘vivo%’)

GET /product/_search
{"query": {"prefix": {"title": {"value": "vivo"  // 小寫查詢,大寫無結果}}}
}返回結果:
{"took" : 11,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "product","_type" : "_doc","_id" : "3","_score" : 1.0,"_source" : {"id" : 3,"title" : "VIVO手機","category" : "vivo","images" : "http://www.vivo.com/sj.jpg","price" : 3600}}]}
}

在這里插入圖片描述


5. 關鍵字精確查詢(term)


因為精確查詢的字段是不分詞的(keyword),因此查詢的條件也必須是不分詞的詞條。

精確查詢要求輸入的內容與字段的值完全一致才能匹配成功。如果用戶輸入的內容過多或與字段的值不完全一致,可能導致無法找到匹配的數(shù)據(jù)。

term查詢語法如下:

GET /{索引名稱}/_search
{"query": {"term": {"FIELD": {"value": "VALUE"}}}
}

示例1:根據(jù)title字段做精確查詢

GET /product/_search
{"query": {"term": {"title": {"value": "華為手機"}}}
}

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-sqIcuiPA-1690304845296)(assets/image-20230721165258197.png)]

示例2:根據(jù)category字段做精確查詢

GET /product/_search
{"query": {"term": {"category": {"value": "華為"}}}
}

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2uOvLhE1-1690304845296)(assets/image-20230722142451229.png)]


6. 多個關鍵字精確查詢(terms)


terms 查詢用于匹配多個關鍵字。我們使用 terms查詢來匹配字段 field 的值是否與給定數(shù)組中的任何一個值相匹配。如果有匹配的文檔,它們將被返回。

terms查詢語法如下:

GET /{索引名稱}/_search
{"query": {"term": {"FIELD":[value1,value2]}}
}

示例:根據(jù)title字段多個關鍵字精確查詢 華為手機,華為

GET /product/_search
{"query": {"terms": {"title": ["華為手機","華為"]}}
}返回結果:
{"took" : 0,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 2,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "product","_type" : "_doc","_id" : "1","_score" : 1.0,"_source" : {"id" : 1,"title" : "華為筆記本電腦","category" : "華為","images" : "http://www.huawei.com/dn.jpg","price" : 5388}},{"_index" : "product","_type" : "_doc","_id" : "2","_score" : 1.0,"_source" : {"id" : 2,"title" : "華為手機","category" : "華為","images" : "http://www.huawei.com/sj.jpg","price" : 5500}}]}
}

7. 范圍查詢(range)


通過range查詢限定字段查詢的范圍:

  • gte: 大于等于
  • lte: 小于等于
  • gt: 大于
  • lt: 小于

range查詢語法如下:

GET /{indexName}/_search
{"query": {"range": {"FIELD": {//范圍條件"xxx":value}}}
}

示例:查詢價格為3000到5000的產品

GET /product/_search
{"query": {"range": {"price": {"gte": 3000,"lte": 5000}}}
}

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Cc01b8xJ-1690304845296)(assets/image-20230722172425023.png)]


8 返回指定字段(_source)


通過_source屬性來指定需要返回的字段。 它的位置與query屬性平級。

返回指定字段語法:

GET /{索引庫名稱}/_search
{"query": {},"_source": ["field1","field2"]
}

示例:返回title和category字段數(shù)據(jù)(類似 select title,category from product where price between 3000 and 5000 )

GET /product/_search
{"query": {"range": {"price": {"gte": 3000,"lte": 5000}}},"_source": ["title","category"]
}

在這里插入圖片描述


9. 組合查詢(bool)


布爾查詢是一個或多個查詢子句的組合,每一個子句就是一個子查詢

以下是對四種布爾操作符的總結:(他們之間可以組合使用)

  • must: 所有條件都必須滿足,即它們之間是 “與”(AND)關系。(會相關性算分)
  • should: 至少有一個條件滿足即可,即它們之間是 “或”(OR)關系。
  • must_not: 所有條件都不能滿足,即它們之間是 “非”(NOT)關系。
  • filter: 該操作符和 must 的效果相同,但它不計算得分,僅用于過濾文檔,因此效率更高。

示例:

GET /my_index/_search
{"query": {"bool": {"must": [{ "term": { "field1": "value1" } },{ "range": { "field2": { "gte": 10, "lte": 20 } } }],"should": [{ "term": { "field3": "value3" } },{ "term": { "field4": "value4" } }],"must_not": [{ "term": { "field5": "value5" } }],"filter": [{ "term": { "field6": "value6" } }]}}
}

在上面的示例中,must 布爾子句指定了字段 field1 的值必須是 “value1”,并且字段 field2 的值必須在 10 到 20 之間。

should 布爾子句指定了字段 field3 的值應該是 “value3”,或者字段 field4 的值應該是 “value4”,其中滿足任意一個條件即可。

must_not 布爾子句指定了字段 field5 的值不能是 “value5”。

filter 布爾子句是一個與 must 相同的過濾條件,它也要求字段 field6 的值必須是 “value6”,但它不計算得分。


9.1 must(并且)


在ES中,你可以使用must關鍵字來表示查詢條件的與操作。must子句中的所有條件都必須滿足才能匹配文檔。

語法如下:

GET /{索引庫名稱}/_search
{"query": {"bool": {"must": [{ 查詢條件1 },{ 查詢條件2}]}}
}

示例:布爾查詢title字段包含華為,并且價格在[3000, 5000]之間的數(shù)據(jù)

GET /product/_search
{"query": {"bool": {"must": [{"match": {"title": "華為"}},{"range": {"price": {"gte": 3000,"lte": 5000}}}]}}
}

在這里插入圖片描述

9.2 should(或者)


示例:布爾查詢title字段包含華為,或者價格在[3000, 5000]之間的數(shù)據(jù)

GET /product/_search
{"query": {"bool": {"should": [{"match": {"title": "華為"}},{"range": {"price": {"gte": 3000,"lte": 5000}}}]}}
}返回結果:
{"took" : 3,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 3,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "product","_type" : "_doc","_id" : "3","_score" : 1.0,"_source" : {"id" : 3,"title" : "VIVO手機","category" : "vivo","images" : "http://www.vivo.com/sj.jpg","price" : 3600}},{"_index" : "product","_type" : "_doc","_id" : "2","_score" : 0.5619608,"_source" : {"id" : 2,"title" : "華為手機","category" : "華為","images" : "http://www.huawei.com/sj.jpg","price" : 5500}},{"_index" : "product","_type" : "_doc","_id" : "1","_score" : 0.35411233,"_source" : {"id" : 1,"title" : "華為筆記本電腦","category" : "華為","images" : "http://www.huawei.com/dn.jpg","price" : 5388}}]}
}

9.3 must_not(非)


must_not:必須不匹配,不參與算分,類似“非”。

需求:布爾查詢title字段不包含華為,并且價格在不在[2000, 3000]之間的數(shù)據(jù)

GET /product/_search
{"query": {"bool": {"must_not": [{"match": {"title": "華為"}},{"range": {"price": {"gte": 2000,"lte": 3000}}}]}}
}返回結果:
{"took" : 1,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 0.0,"hits" : [{"_index" : "product","_type" : "_doc","_id" : "3","_score" : 0.0,"_source" : {"id" : 3,"title" : "VIVO手機","category" : "vivo","images" : "http://www.vivo.com/sj.jpg","price" : 3600}}]}
}

9.4 filter


filter: 與must的效果相同(and),但它不計算得分,僅用于過濾文檔,因此效率更高。(計算得分會影響查詢性能)

_score的分值為0

GET /product/_search
{"query": {"bool": {"filter": [{"match": {"title": "華為"}}]}}
}返回結果:
{"took" : 0,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 2,"relation" : "eq"},"max_score" : 0.0,"hits" : [{"_index" : "product","_type" : "_doc","_id" : "1","_score" : 0.0,"_source" : {"id" : 1,"title" : "華為筆記本電腦","category" : "華為","images" : "http://www.huawei.com/dn.jpg","price" : 5388}},{"_index" : "product","_type" : "_doc","_id" : "2","_score" : 0.0,"_source" : {"id" : 2,"title" : "華為手機","category" : "華為","images" : "http://www.huawei.com/sj.jpg","price" : 5500}}]}
}

10. 聚合查詢(aggs)


Elasticsearch的聚合查詢是一種強大的功能,可以對文檔進行統(tǒng)計分析和數(shù)據(jù)聚合。聚合查詢可以幫助你從大量的數(shù)據(jù)中提取有用的信息和洞察。它提供了許多不同類型的聚合,可以用于計算最大值、最小值、平均值、求和等等。

以下是一些常見的聚合類型:

  1. avg:計算一個字段的平均值。
  2. sum:計算一個字段的總和。
  3. min:找到一個字段的最小值。
  4. max:找到一個字段的最大值。
  5. cardinality:計數(shù)一個字段的唯一值數(shù)量。
  6. stats:計算一個字段的統(tǒng)計數(shù)據(jù),包括最小值、最大值、平均值和總和。
  7. extended_stats:在 stats 的基礎上,還提供方差、標準差和其他分位數(shù)等更詳細的統(tǒng)計數(shù)據(jù)。
  8. percentiles:計算一個字段的百分位數(shù)。
  9. bucket(桶)聚合:將文檔分組為不同的桶,并對每個桶內的文檔應用其他聚合函數(shù)。

10.1 max


示例:計算 price字段的最大值。

GET /product/_search
{"query": {"match_all": {}},"aggs": {"max_price": { //給聚合結果指定一個名字"max": {"field": "price"}}}
}

在這里插入圖片描述

上面查詢的結果攜帶著原始文檔數(shù)據(jù),我們可以通過設置 "size" 參數(shù)來控制聚合查詢返回的文檔數(shù)量。將 "size" 參數(shù)設置為 0,可以使查詢只返回聚合結果,不返回原文檔數(shù)據(jù)。(如果size為100,則表示返回前100個原文檔)

GET /product/_search
{"query": {"match_all": {}},"size": 0, "aggs": {"max_price": {"max": {"field": "price"}}}
}

在這里插入圖片描述


10.2 min


示例:計算 price字段的最小值。

GET /product/_search
{"query": {"match_all": {}},"size": 0, "aggs": {"min_price": {"min": {"field": "price"}}}
}

在這里插入圖片描述


10.3 avg


示例:計算 price字段的平均值。

GET /product/_search
{"query": {"match_all": {}},"size": 0, "aggs": {"avg_price": {"avg": {"field": "price"}}}
}

在這里插入圖片描述


10.4 sum


示例:計算 price字段的總和。

GET /product/_search
{"query": {"match_all": {}},"size": 0, "aggs": {"sum_price": {"sum": {"field": "price"}}}
}

在這里插入圖片描述


10.5 stats


stats聚合用于計算一個字段的統(tǒng)計數(shù)據(jù),包括:最小值、最大值、求和、平均值和數(shù)據(jù)數(shù)量。

示例:統(tǒng)計price字段的數(shù)據(jù)

GET /product/_search
{"query": {"match_all": {}},"size": 0, "aggs": {"total_stats": {"stats": {"field": "price"}}}
}

在這里插入圖片描述


10.6 terms(分組)


terms(桶聚合)用于對字段進行分組統(tǒng)計(類似mysql中的group by)。它將文檔按照指定字段的值進行分組,并計算每個分組的文檔數(shù)量或其他指標。

示例:按照category分組,統(tǒng)計文檔個數(shù)。(對比sql:select category,count(*) as count from product group by category)

GET /product/_search
{"query": {"match_all": {}},"size": 0, "aggs": {"stats_price": {"terms": {"field": "category"}}}
}

在這里插入圖片描述

示例:按照category字段進行分組,只拿到前兩個分組數(shù)據(jù),并對每組的price計算總和。

GET /product/_search
{"query": {"match_all": {}},"size": 0, "aggs": {"terms_category": {"terms": {"field": "category","size": 2},"aggs": {"agg_sum": {"sum": {"field": "price"}}}}}
}

在這里插入圖片描述


11. 分頁查詢(from、size)


分頁的兩個關鍵屬性:from、size。

  • from: 當前頁的起始索引,默認從0開始。 from = (pageNum - 1) * size
  • size: 每頁顯示多少條

分頁查詢語法如下:

GET /{indexName}/_search
{"query": {"match_all": {}},"from": 0, // 分頁開始的位置,默認為0"size": 10, // 每頁顯示多少條"sort": [ //根據(jù)filed字段進行排序{"filed": "asc或desc"}]
}

示例:全文檢索華為手機,然后對price字段做倒排序,并實現(xiàn)分頁。

GET /product/_search
{"query": {"match": {"title": "華為手機"}},"sort": [{"price": {"order": "desc"}}],"from": 0,"size": 2
}

在這里插入圖片描述


12. 高亮查詢(highlight)


高亮原理:

比如我們在百度上搜索資料時,命中關鍵字的文檔會變成紅色,比較醒目,這就是高亮顯示。
在這里插入圖片描述

高亮顯示的實現(xiàn)分為兩步:

  1. 給文檔中的所有關鍵字都添加一個標簽,例如<em>標簽;

  2. 頁面給<em>標簽編寫CSS樣式。


在es中實現(xiàn)高亮:

高亮顯示語法:

GET /hotel/_search
{"query": {"match": {"FIELD": "TEXT" // 查詢條件,高亮一定要使用全文檢索查詢}},"highlight": {"fields": { "FIELD": {// 指定要高亮的字段"pre_tags": "<em>",  // 用來標記高亮字段的前置標簽"post_tags": "</em>" // 用來標記高亮字段的后置標簽}}}
}

示例:全文檢索查詢華為手機,對title字段進行高亮處理。

GET /product/_search
{"query": {"match": {"title": "華為手機"}},"highlight": {"fields": {"title": {"pre_tags": "<em>","post_tags":"</em>"}}}
}

在這里插入圖片描述

注意:

  • 高亮是對關鍵字高亮,因此搜索條件必須帶有關鍵字,而不能是范圍這樣的查詢。
  • 默認情況下,高亮的字段,必須與搜索指定的字段一致,否則無法高亮。
  • 如果要對非搜索字段高亮,則需要在高亮字段中添加一個屬性:required_field_match=false

在這里插入圖片描述


13. 近似查詢(fuzzy)


fuzzy查詢是一種糾錯查詢,通常用于英文的糾錯。它可以返回與搜索詞相似的詞的文檔。

編輯距離是衡量兩個詞之間差異程度的指標,表示將一個詞轉換為另一個詞所需的最小操作次數(shù)。

這些操作包括:

  • 更改字符(box → fox)

  • 刪除字符(black → lack)

  • 插入字符(sic → sick)

  • 轉置兩個相鄰字符(act → cat)

在fuzzy查詢中,我們可以通過調整fuzziness參數(shù)來修改編輯距離。默認值為AUTO(根據(jù)單詞的長度匹配對應的編輯距離),fuzziness參數(shù)其它取值為0,1,2 表示最大編輯距離。

  • 當單詞長度為0到2之間時,必須精確匹配。編輯距離為0。(不會進行變化)
  • 當單詞長度為3到5個字母時,最大編輯距離為1。(例如 hallo->hello)
  • 當單詞長度大于5個字母時,最大編輯距離為2(最多允許兩次編輯)。

示例:近似查詢categroy字段值為vovo的文檔

GET /product/_search
{"query": {"fuzzy": {"category": {"value": "vovo", "fuzziness": 1}}}
}

在這里插入圖片描述


七、Java操作ES


1. API介紹


文檔地址:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.x/java-rest-high-getting-started.html

(1)使用官網提供的API操作ES: (RestHighLevelClient)

在這里插入圖片描述

maven坐標:

<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.12.1</version>
</dependency>

(2)Spring Data ElasticSearch: 是Spring針對ElasticSearch提供的一個模塊,底層是對ES官方所提供的Java API進行了封裝,用來簡化ES的操作。

在這里插入圖片描述

maven坐標:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

2. 使用RestHighLevelClient操作ES


RestHighLevelClient是ES官網提供的API。

2.1 環(huán)境準備


1、創(chuàng)建maven項目

2、導入依賴:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.aopmin</groupId><artifactId>RestHighLevelClient-demo</artifactId><version>1.0-SNAPSHOT</version><!-- springboot工程 --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.5</version><relativePath/> <!-- lookup parent from repository --></parent><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--Spring Data Elasticsearch由于Spring Data Elasticsearch底層封裝了Elasticsearch官方的Java API,因此把這個依賴加入進來以后,關于RestHighLevelClient已經由SpringBoot進行自動配置了--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency><!-- junit --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><!-- fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.80</version></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build>
</project>

3、創(chuàng)建啟動類:

package cn.aopmin;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class MyApp {public static void main(String[] args) {SpringApplication.run(MyApp.class, args);}
}

4、在application.yml中配置ES:

spring:elasticsearch:rest:uris: http://192.168.150.123:9200 # 配置es服務器的地址

5、測試

package cn.aopmin.test;import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;
import org.springframework.boot.test.context.SpringBootTest;/*** 測試類* @author 白豆五* @version 2023/07/23* @since JDK8*/
@SpringBootTest
public class ElasticSearchTest {@Autowiredprivate RestHighLevelClient restHighLevelClient;@Testpublic void test() {System.out.println(restHighLevelClient);}
}

在這里插入圖片描述


2.2 索引庫相關操作

2.2.1 創(chuàng)建索引庫


package cn.aopmin.test;import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.io.IOException;/*** 測試索引庫相關操作** @author 白豆五* @version 2023/07/23* @since JDK8*/
@SpringBootTest
@Slf4j
public class IndexTest {@Autowiredprivate RestHighLevelClient restHighLevelClient;/*** 測試創(chuàng)建索引庫*/@Testpublic void testCreateIndex() throws IOException {// 1.拿到創(chuàng)建索引的請求對象,并指定索引名// org.elasticsearch.client.indices.CreateIndexRequest;CreateIndexRequest createIndexRequest = new CreateIndexRequest("goods");// 2.添加請求參數(shù)(內容是定義索引庫的DSL語句,json格式)// 也可以把DSL語句提取到常量類中createIndexRequest.source("{\n" +"  \"mappings\": {\n" +"    \"properties\": {\n" +"      \"id\":{\n" +"        \"type\": \"long\",\n" +"        \"index\": true\n" +"      },\n" +"      \"title\": {\n" +"        \"type\": \"text\",\n" +"        \"index\": true,\n" +"        \"analyzer\": \"ik_max_word\",\n" +"        \"search_analyzer\": \"ik_smart\"\n" +"      },\n" +"      \"category\": {\n" +"        \"type\": \"keyword\",\n" +"        \"index\": true\n" +"      },\n" +"      \"images\": {\n" +"        \"type\": \"keyword\",\n" +"        \"index\": false\n" +"      },\n" +"      \"price\": {\n" +"        \"type\": \"integer\",\n" +"        \"index\": true\n" +"      }\n" +"    }\n" +"  }\n" +"}", XContentType.JSON);// 3.發(fā)送請求// IndicesClient indices = restHighLevelClient.indices(); // 拿到操作索引的客戶端// indices.create(createIndexRequest, RequestOptions.DEFAULT); // 執(zhí)行創(chuàng)建索引的請求// CreateIndexResponse對象中包含了創(chuàng)建索引的返回結果CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);// 4.輸出結果log.info("索引名稱:{}", createIndexResponse.index());log.info("操作是否成功:{}", createIndexResponse.isAcknowledged());log.info("分片是否被確認:{}", createIndexResponse.isShardsAcknowledged());}
}

在這里插入圖片描述在這里插入圖片描述


2.2.2 獲取所引庫


/*** 測試獲取索引庫*/
@Test
public void testGetIndex() throws IOException {// 1.創(chuàng)建Request對象GetIndexRequest getIndexRequest = new GetIndexRequest("goods");// 2.發(fā)起請求, exists()方法返回true表示索引庫存在,false表示不存在boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);log.info("索引庫是否存在:{}", exists);
}

在這里插入圖片描述


2.2.3 刪除索引庫


/*** 測試刪除索引庫*/
@Test
public void testDeleteIndex() throws IOException {DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("goods");AcknowledgedResponse response = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);System.out.println("索引庫是否刪除成功: "+response.isAcknowledged());
}

在這里插入圖片描述


小節(jié):

RestHighLevelClient操作ES索引庫的流程基本類似。核心都是通過restHighLevelClient.indices()方法獲取索引庫的操作對象。

索引庫操作的基本步驟如下:

  • 依賴注入RestHighLevelClient。(Spring Data Elasticsearch依賴提供的)
  • 創(chuàng)建XxxIndexRequest。(Xxx是Create、Delete、Get。)
  • 準備DSL( 只有在Create時需要準備DSL)
  • 發(fā)送請求。(調用RestHighLevelClient.indices().xxx()方法,xxx是create、exists、delete、get)

2.3 文檔相關操作


2.3.1 數(shù)據(jù)準備


1、sql腳本:

CREATE DATABASE IF NOT EXISTS `es-db` DEFAULT CHARACTER SET utf8mb4;use `es-db`;CREATE TABLE `goods`
(`id`       BIGINT(20) PRIMARY KEY AUTO_INCREMENT COMMENT '商品ID',`title`    VARCHAR(255) NOT NULL COMMENT '商品標題',`category` VARCHAR(32)  NOT NULL COMMENT '分類',`image`    VARCHAR(255) NOT NULL COMMENT '圖片',`price`    INT(10)      NOT NULL COMMENT '價格'
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT '商品表';insert into goods values (1, '華為筆記本電腦', '華為', 'http://www.huawei.com/dn.jpg', 5388),(2, '華為手機', '華為', 'http://www.huawei.com/sj.jpg', 5500),(3, 'VIVO手機', 'vivo', 'http://www.vivo.com/sj.jpg', 3600);

2、引入mp相關依賴:

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version>
</dependency>

3、在application.yml中配置數(shù)據(jù)庫:

spring:# 數(shù)據(jù)源配置datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql:///es-db?useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456# ES配置elasticsearch:rest:uris: http://192.168.150.123:9200 # 配置es服務器的地址

4、使用插件生成pojo、mappe、service基礎代碼

在這里插入圖片描述

1)數(shù)據(jù)源配置:

在這里插入圖片描述

2)使用代碼生成器:

在這里插入圖片描述

在這里插入圖片描述

5、在啟動類上配置mapper掃描:

package cn.aopmin;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@MapperScan("cn.aopmin.mapper") //mapper掃描
@SpringBootApplication
public class MyApp {public static void main(String[] args) {SpringApplication.run(MyApp.class, args);}
}

2.3.2 添加文檔


package cn.aopmin.test;import cn.aopmin.pojo.Goods;
import cn.aopmin.service.IGoodsService;
import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import javax.annotation.Resource;
import java.io.IOException;/*** @author 白豆五* @version 2023/07/23* @since JDK8*/
@SpringBootTest
public class DocumentTest {@Resourceprivate IGoodsService goodsService;@Resourceprivate RestHighLevelClient client;/*** 測試創(chuàng)建文檔*/@Testpublic void testAddDocument() throws IOException {// 1.創(chuàng)建Request對象// IndexRequest: 創(chuàng)建文檔的請求對象IndexRequest request = new IndexRequest("goods"); //指定索引庫名稱// 設置文檔id,如果不設置的話,ES會自動生成一個唯一的字符串作為文檔IDrequest.id("10");// 2.準備json文檔數(shù)據(jù)// Java對象轉JSON字符串String json = JSON.toJSONString(new Goods().setId(10L).setTitle("小辣椒手機").setCategory("小辣椒").setImage("https://xiaolajiao.cn").setPrice(1388));request.source(json, XContentType.JSON);// 3.發(fā)送請求創(chuàng)建文檔IndexResponse response = client.index(request, RequestOptions.DEFAULT);// 輸出結果System.out.println(response.getResult());}}

執(zhí)行結果:
在這里插入圖片描述在這里插入圖片描述


2.3.3 修改文檔


修改文檔有兩種方式:

  • 全量修改:本質是先根據(jù)id刪除,再新增(語法與插入文檔類似)
  • 增量修改:修改文檔中的指定字段值
/*** 測試修改文檔*/
@Test
public void testUpdateDocument() throws IOException {// 構建數(shù)據(jù)Goods goods = new Goods();goods.setPrice(999);String jsonString = JSON.toJSONString(goods);// 1.創(chuàng)建Request對象// UpdateRequest: 修改文檔的請求對象。參數(shù):索引庫、文檔id。如果文檔id不存在,則會新增一個文檔。UpdateRequest request = new UpdateRequest("goods", "10");// 2.準備Json文檔,里面包含要修改的字段request.doc(jsonString, XContentType.JSON);// 3.發(fā)送請求UpdateResponse response = client.update(request, RequestOptions.DEFAULT);// 4.輸出結果System.out.println(response.getResult());
}

輸出結果:

在這里插入圖片描述
在這里插入圖片描述


2.3.4 根據(jù)id查詢文檔


/*** 測試根據(jù)id查詢文檔*/
@Test
public void testGetDocument() throws IOException {// 1.創(chuàng)建Request對象// DSL: GET /goods/_doc/10GetRequest request = new GetRequest("goods", "10");// 2.發(fā)送請求GetResponse response = client.get(request, RequestOptions.DEFAULT);// 3.輸出文檔內容System.out.println("_source: "+response.getSourceAsString());
}

執(zhí)行結果:

在這里插入圖片描述在這里插入圖片描述


2.3.5 刪除文檔


/*** 測試根據(jù)id刪除文檔*/
@Test
public void testDeleteDocument() throws IOException {// 1.創(chuàng)建Request對象// DSL: DELETE /goods/_doc/10DeleteRequest request = new DeleteRequest("goods", "10");// 2.發(fā)送請求client.delete(request, RequestOptions.DEFAULT);
}

2.3.6 批量新增


批量處理BulkRequest,其本質就是將多個普通的CRUD請求組合在一起發(fā)送。

其中提供了一個add方法,用來添加其他Request請求:

  • IndexRequest,新增文檔的請求
  • UpdateRequest,修改文檔的請求
  • DeleteRequest,刪除文檔的請求

在這里插入圖片描述

示例:將數(shù)據(jù)庫中的數(shù)據(jù)添加到

/*** 測試批量新增*/
@Test
public void testBulkAddDocument() throws IOException {// 準備數(shù)據(jù)List<Goods> goodsList = goodsService.list();// 1.創(chuàng)建Request對象// BulkRequest: 批量操作請求對象??梢耘繄?zhí)行增刪改操作BulkRequest bulkRequest = new BulkRequest();// 2.準備參數(shù):把多個IndexRequest添加到BulkRequest中goodsList.forEach(goods -> {//對象轉Json字符串String json = JSON.toJSONString(goods);//創(chuàng)建單個請求對象/*IndexRequest request = new IndexRequest("goods");request.id(goods.getId().toString()); //文檔idrequest.source(json, XContentType.JSON);//Josn文檔內容bulkRequest.add(request);//放入批量請求對象中*/// 簡化寫法bulkRequest.add(new IndexRequest("goods").id(goods.getId().toString()).source(json, XContentType.JSON));});// 3.發(fā)送批處理請求BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
}

在這里插入圖片描述

批量新增操作步驟:

  • 創(chuàng)建Request對象,這里是BulkRequest。
  • 準備參數(shù)。批處理的參數(shù),把多個IndexRequest添加到BulkRequest中。
  • 發(fā)送批處理請求。調用的方法為client.bulk()方法。

小節(jié):

文檔操作的基本步驟:

  • 注入RestHighLevelClient對象
  • 創(chuàng)建XxxRequest。如 IndexRequest、GetRequest、UpdateRequest、DeleteRequest、BulkRequest
  • 準備參數(shù)(Index、Update、Bulk時需要提供)
  • 發(fā)送請求。調用RestHighLevelClient.xxx()方法,xxx是index、get、update、delete、bulk
  • 解析結果(Get時需要)

2.4 高級查詢


2.4.1 查詢所有文檔


package cn.aopmin.test;import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.io.IOException;/*** 高級查詢** @author 白豆五* @version 2023/07/24* @since JDK8*/
@SpringBootTest
public class DSLTest {@Autowiredprivate RestHighLevelClient restHighLevelClient;/*** 測試查詢所有文檔*/@Testpublic void testMatchAll() throws IOException {// 1.構建SearchRequest對象SearchRequest searchRequest = new SearchRequest("my_index");// 2.創(chuàng)建一個SearchSourceBuilder對象,并設置查詢條件SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.matchAllQuery());//matchAllQuery()查詢所有// 設置查詢條件searchRequest.source(searchSourceBuilder);// 3.發(fā)送請求,調用restHighLevelClient的search方法SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);// 4.解析響應結果// 從response對象中獲取hits返回結果數(shù)據(jù)SearchHits responseHits = response.getHits();// 獲取查詢到的文檔列表:hists[]SearchHit[] searchHits = responseHits.getHits();for (SearchHit searchHit : searchHits) {// 獲取文檔的原數(shù)據(jù)(json數(shù)據(jù))String jsonData = searchHit.getSourceAsString();System.out.println(jsonData);}}
}

返回結果:
在這里插入圖片描述在這里插入圖片描述


2.4.2 匹配查詢


/*** 測試匹配查詢(全文檢索,單字段)*/
@Test
public void testMatch() throws IOException {// 1.構建SearchRequest對象SearchRequest searchRequest = new SearchRequest("goods");// 2.創(chuàng)建一個SearchSourceBuilder對象,并設置查詢條件SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.matchQuery("title", "華為"));//matchQuery()匹配查詢// 設置查詢條件searchRequest.source(searchSourceBuilder);// 3.發(fā)送查詢請求SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);// 4.解析響應結果// 從response對象中獲取hits返回結果數(shù)據(jù)SearchHits responseHits = response.getHits();// 獲取查詢到的文檔列表:hists[]SearchHit[] searchHits = responseHits.getHits();for (SearchHit searchHit : searchHits) {// 獲取文檔的原數(shù)據(jù)(json數(shù)據(jù))String jsonData = searchHit.getSourceAsString();System.out.println(jsonData);}
}

返回結果:
在這里插入圖片描述


2.4.3 高亮查詢


/*** 高亮查詢*/
@Test
public void testHighLight() throws IOException {// 1.構建SearchRequest對象SearchRequest searchRequest = new SearchRequest("goods");// 2.創(chuàng)建一個SearchSourceBuilder對象,并設置查詢條件SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.matchQuery("title", "華為"));//matchQuery()匹配查詢// 3.對searchSourceBuilder對象設置高亮參數(shù)HighlightBuilder highlighter = new HighlightBuilder();highlighter.field("title");//設置高亮字段highlighter.preTags("<em>");//設置高亮前綴highlighter.postTags("</em>");//設置高亮后綴searchSourceBuilder.highlighter(highlighter);// 4.設置查詢條件searchRequest.source(searchSourceBuilder);// 5.發(fā)送查詢請求SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);// 6.解析響應結果// 從response對象中獲取hits返回結果數(shù)據(jù)SearchHits responseHits = response.getHits();// 獲取查詢到的文檔列表:hists[]SearchHit[] searchHits = responseHits.getHits();for (SearchHit searchHit : searchHits) {// 獲取文檔數(shù)據(jù)String jsonData = searchHit.getSourceAsString();Goods goods = JSON.parseObject(jsonData, Goods.class);//  獲取高亮數(shù)據(jù)Map<String, HighlightField> map = searchHit.getHighlightFields();if (map != null) {//獲取高亮字段的值: 一個數(shù)組HighlightField highlightField = map.get("title");if (highlightField != null ) {String title = highlightField.getFragments()[0].toString();goods.setTitle(title);}}System.out.println(JSON.toJSONString(goods));}
}

在這里插入圖片描述在這里插入圖片描述

簡化寫法:

@Test
public void testHighLight2() throws IOException {// 1.構建SearchRequest對象SearchRequest searchRequest = new SearchRequest("goods");// 2.準備DSL/*// 2.1設置查詢條件searchRequest.source().query(QueryBuilders.matchQuery("title", "華為"));// 2.2設置高亮參數(shù)searchRequest.source().highlighter(new HighlightBuilder().field("title").preTags("<em>").postTags("</em>"));*/searchRequest.source()// 設置查詢條件.query(QueryBuilders.matchQuery("title", "華為"))// 設置高亮參數(shù).highlighter(new HighlightBuilder().field("title").preTags("<em>").postTags("</em>"));// 3.發(fā)送查詢請求SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);// 4.解析響應結果// 從response對象中獲取hits返回結果數(shù)據(jù)SearchHits responseHits = response.getHits();// 獲取查詢到的文檔數(shù)組:hists[]SearchHit[] searchHits = responseHits.getHits();// 4.1獲取總條數(shù)long total = searchHits.length;System.out.println("共搜索到" + total + "條數(shù)據(jù)");for (SearchHit searchHit : searchHits) {// 4.2獲取文檔數(shù)據(jù)(_source)String jsonData = searchHit.getSourceAsString();Goods goods = JSON.parseObject(jsonData, Goods.class);// 4.3獲取高亮數(shù)據(jù)Map<String, HighlightField> map = searchHit.getHighlightFields();if (map != null) {//根據(jù)字段名獲取高亮結果HighlightField highlightField = map.get("title");if (highlightField != null) {// 獲取高亮值String title = highlightField.getFragments()[0].toString();// 覆蓋內容goods.setTitle(title);}}System.out.println(JSON.toJSONString(goods));}
}

在這里插入圖片描述

這里面有兩個關鍵的API,一個是request.source(),提供了查詢、排序、分頁、高亮等功能:

在這里插入圖片描述

另一個是QueryBuilders工具類,可以進行match、term、function_score、bool等查詢:
在這里插入圖片描述


2.4.4 聚合查詢


/*** 測試聚合查詢*/
@Test
public void testAggs() throws IOException {// 1.創(chuàng)建Request對象SearchRequest request = new SearchRequest("goods");// 2.準備DSL// 2.1設置查詢條件request.source().query(QueryBuilders.matchQuery("title", "華為")).size(0) //不需要返回文檔數(shù)據(jù),只需要返回聚合結果// 2.2設置聚合參數(shù).aggregation(AggregationBuilders.terms("group_category").field("category")) //根據(jù)category字段進行分組.aggregation(AggregationBuilders.avg("avg_price").field("price"));//根據(jù)price字段求平均值// 3.發(fā)起請求,獲取響應結果SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);// 4.解析響應結果// 4.1獲取聚合結果,Map<String, Aggregation>Aggregations aggregations = response.getAggregations();// 4.2獲取group_category子聚合數(shù)據(jù)Terms terms = aggregations.get("group_category");terms.getBuckets().forEach(bucket -> {System.out.println("key:" + bucket.getKeyAsString());System.out.println("docCount:" + bucket.getDocCount());});// 4.3獲取avg_price子聚合數(shù)據(jù)Avg avg = aggregations.get("avg_price");System.out.println("avg_price:" + avg.getValue());
}

輸出結果:

在這里插入圖片描述在這里插入圖片描述

3. 使用Spring Data Elasticsearch 操作ES


ElasticsearchRestTemplate是Spring Data Elasticsearch框架提供的API。

3.1 Spring Data概述


Spring Data是Spring家族的一個子項目,其目的:用于簡化持久層的開發(fā)(如 關系型數(shù)據(jù)庫、非關系型數(shù)據(jù)庫、索引庫的訪問),并且它提供統(tǒng)一的API以訪問各種數(shù)據(jù)存儲技術。

Spring Data可以極大的簡化JPA(Java Persistence API,Java持久層API)的寫法,可以在幾乎不用寫實現(xiàn)的情況下,實現(xiàn)對數(shù)據(jù)的訪問和操作。除了CRUD外,還包括如分頁、排序等一些常用的功能。

SpringData提供了一些XxxTemplate對象,用于簡化各種數(shù)據(jù)庫的操作,如:

  • JdbcTemplate:JdbcTemplate是Spring Data對關系型數(shù)據(jù)庫(如MySQL、Oracle等)進行操作的模板對象。它提供了一組方法,用于執(zhí)行SQL語句、處理結果集、事務管理等。
  • MongoTemplate:MongoTemplate是Spring Data對MongoDB進行操作的模板對象。它提供了一組方法,用于執(zhí)行CRUD操作、查詢、更新等。
  • RedisTemplate:RedisTemplate是Spring Data對Redis進行操作的模板對象。它提供了一組方法,用于執(zhí)行常見的Redis操作,如存儲、獲取、刪除數(shù)據(jù)等。
  • ElasticsearchRestTemplate:ElasticsearchRestTemplate是Spring Data對Elasticsearch進行操作的模板對象。它提供了一組方法,用于執(zhí)行CRUD操作、搜索、聚合等。
    在這里插入圖片描述

3.2 Spring Data Elasticsearch 概述


Spring Data Elasticsearch基于Spring Data API對Elasticsearch進行了封裝,使開發(fā)者能夠更高效地使用Elasticsearch進行數(shù)據(jù)存儲和搜索。

Spring Data Elasticsearch版本選擇:(不同版本會存在差異)
在這里插入圖片描述

springboot2.3.x版本可以兼容elasticsearch7.x版本。


3.3 環(huán)境準備


1、創(chuàng)建maven項目

2、導入依賴:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.aopmin</groupId><artifactId>SpringDataElasticsearch-demo</artifactId><version>1.0-SNAPSHOT</version><!-- springboot工程 --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.10.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!-- Spring Data Elasticsearch --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId>   </dependency><!-- junit --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><!-- fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.80</version></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

3、創(chuàng)建啟動類:

package cn.aopmin;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringDataElasticsearchApplication {public static void main(String[] args) {SpringApplication.run(SpringDataElasticsearchApplication.class, args);}
}

4、在application.yml中配ES:

spring:elasticsearch:rest:uris: http://192.168.150.123:9200 # 配置es服務器的地址

5、創(chuàng)建實體類:(通過注解與es進行綁定)

package cn.aopmin.pojo;import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "product", // 索引庫名稱shards = 1, // 主分片個數(shù)replicas = 1 // 備份分片個數(shù)
)
public class Product {/*** 主鍵id*/// ES主鍵id@Idprivate Long id;/*** 商品名稱*/// ES普通字段@Field(type = FieldType.Text, // 字段類型analyzer = "ik_max_word", // 建立索引用的分詞器searchAnalyzer = "ik_smart", //查詢時用的分詞器store = true // 是否額外存儲一份 (ES默認把文檔字段存儲在源文檔_source中))private String productName;/*** 庫存數(shù)量*/@Field(type = FieldType.Integer, store = true)private Integer store;/*** 價格*/@Field(type = FieldType.Double, store = true)private Double price;
}

注解含義:

1)@Document:作用在類,標記實體類為文檔對象,一般有三個屬性:

  • indexName:對應索引庫名稱

  • shards:分片數(shù)量

  • replicas:副本數(shù)量

2)@Id:作用在成員變量,標記一個字段作為id主鍵。

3)@Field:作用在成員變量,標記為文檔的字段,并指定字段映射屬性:

  • type:字段類型,取值是枚舉:FieldType.xxx

  • index:是否建立索引,布爾類型,默認是true

  • store:是否存儲,布爾類型,默認是false 不額外存儲一份 (場景:只返回某個特定字段,此時可以提高查詢效率。但是對寫入效率會有影響)

  • analyzer:分詞器名稱:ik_max_word(建立倒排索引時所使用的分詞算法)

store 的意思是:是否在 _source 之外在獨立存儲一份(提高查詢效率,對寫入會有點影響)
_source 表示源文檔,當你索引數(shù)據(jù)的時候, elasticsearch 會保存一份源文檔到 _source ,
如果文檔的某一字段設置了 store 為 yes (默認為 no),這時候會在 _source 存儲之外再為這個字段獨立進行存儲。這么做的目的主要是針對內容比較多的字段,放到 _source 返回的話,因為_source 是把所有字段保存為一份文檔,命中后讀取只需要一次 IO,包含內容特別多的字段會很占帶寬影響性能。
通常我們也不需要完整的內容返回(可能只關心某個字段),這時候就沒必要放到 _source 里一起返回了(當然也可以在查詢時指定返回字段)。

6、測試

@SpringBootTest
public class SpringDataElasticsearchTest {@Autowiredprivate ElasticsearchRestTemplate elasticsearchRestTemplate;@Testpublic void test() {System.out.println(elasticsearchRestTemplate);}
}

在這里插入圖片描述


3.4 使用ElasticsearchRestTemplate操作ES


ElasticsearchRestTemplate是Spring Data Elasticsearch中所提供的一個操作ES的核心類,并且已經被Spring Boot實現(xiàn)了自動化配置。

ElasticsearchRestTemplate模板對象常用方法:

  • createIndex:創(chuàng)建索引

  • deleteIndex:刪除索引

  • save:添加文檔

  • get:根據(jù)文檔ID獲取文檔

  • update:更新文檔

  • delete:根據(jù)文檔ID刪除文檔

  • search:執(zhí)行查詢操作

  • exists:檢查文檔是否存在

  • count:統(tǒng)計文檔數(shù)量


3.4.1 添加文檔


package cn.aopmin.test;import cn.aopmin.pojo.Product;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;/*** 測試使用ElasticsearchRestTemplate操作ES* @author 白豆五* @version 2023/07/25* @since JDK8*/
@SpringBootTest
public class SpringDataElasticsearchTest {@Autowiredprivate ElasticsearchRestTemplate elasticsearchRestTemplate;/*** 測試添加文檔*/@Testpublic void testAddDocument() {// 構造數(shù)據(jù)Product product = new Product();product.setId(1L);product.setProductName("華為手機");product.setStore(100);product.setPrice(5000.00);// 添加文檔// 注意:不用提提前創(chuàng)建索引,Spring Data ES會根據(jù)實體類映射關系自動創(chuàng)建索引庫elasticsearchRestTemplate.save(product);}
}

在這里插入圖片描述


3.4.2 根據(jù)ID查詢文檔


在這里插入圖片描述

/*** 測試查詢文檔*/
@Test
public void testGetDocument() {// 查詢文檔// get方法:需要指定文檔id和文檔所在索引庫的類型_classProduct product = elasticsearchRestTemplate.get("1", Product.class);System.out.println(product);
}

在這里插入圖片描述


3.4.3 修改文檔


/*** 測試修改文檔*/
@Test
public void testUpdateDocument() {// 準備數(shù)據(jù)Document document = Document.create();document.put("price", 1899);// 構造一個更新對象UpdateQuery// 參數(shù)1:文檔id// 參數(shù)2:修改的文檔數(shù)據(jù)UpdateQuery updateQuery = UpdateQuery.builder("1").withDocument(document).build();// 修改文檔// 參數(shù)1:updateQuery對象// 參數(shù)2:指定文檔所在的索引庫elasticsearchRestTemplate.update(updateQuery, IndexCoordinates.of("product"));
}

在這里插入圖片描述


3.4.4 刪除文檔


/*** 測試刪除文檔*/
@Test
public void testDeleteDocument() {// 刪除文檔// delete方法:需要指定文檔id和文檔類型elasticsearchRestTemplate.delete("1", Product.class);
}

在這里插入圖片描述


3.4.5 查詢所有文檔


/*** 測試查詢所有文檔*/
@Test
public void testMachAll() {// 構造NativeSearchQuery對象,封裝查詢條件NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery()).build();// 調用search方法進行查詢,返回List<SearchHit<T>>SearchHits<Product> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);List<SearchHit<Product>> list = searchHits.getSearchHits(); //get方法// 遍歷文檔// for (SearchHit<Product> hit : list) {//     Product product = hit.getContent();//     System.out.println(product);// }searchHits.stream().forEach(hit -> System.out.println(hit.getContent()));
}

在這里插入圖片描述

在這里插入圖片描述


3.4.6 高亮查詢


/*** 測試高亮查詢*/
@Test
public void testHighlight() {// 構造高亮參數(shù)HighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.field("productName"); // 設置高亮字段highlightBuilder.preTags("<em>"); // 設置高亮字段的前綴highlightBuilder.postTags("</em>"); // 設置高亮字段的后綴// 創(chuàng)建NativeSearchQuery對象,封裝查詢條件NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("productName", "華為")).withHighlightBuilder(highlightBuilder) // 設置高亮參數(shù).build();// 調用search方法進行查詢SearchHits<Product> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);// 遍歷操作searchHits.stream().forEach(productSearchHit -> System.out.println(productSearchHit));
}

在這里插入圖片描述


3.4.7 分頁查詢


/*** 測試分頁查詢*/
@Test
public void testPage() {// 構造NativeSearchQuery對象,封裝查詢條件NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery()).withPageable(PageRequest.of(0, 2)) // 設置分頁參數(shù).build();// 調用search方法進行查詢SearchHits<Product> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);// 遍歷操作searchHits.stream().forEach(productSearchHit -> System.out.println(productSearchHit));
}

3.4.8 聚合查詢


1、向Product實體類中添加新字段,類型設置為keyword(完整的單詞,不進行分詞):

/*** 分類*/
@Field(type = FieldType.Keyword)
private String category;

2、在kibana中執(zhí)行DSL命令刪除索引庫:DELETE /product

3、添加數(shù)據(jù)

/*** 測試批量插入數(shù)據(jù)*/
@Test
public void testBulkAddDocument() {// 準備數(shù)據(jù)Product product1 = new Product(1L, "華為手機", 200, 2000.00, "華為");Product product2 = new Product(2L, "華為筆記本電腦", 100, 5699.00, "華為");Product product3 = new Product(3L, "VIVO手機", 200, 3600.00, "vivo");// 構造IndexQuery對象List<IndexQuery> indexQueryList = new ArrayList<IndexQuery>();indexQueryList.add(new IndexQueryBuilder().withObject(product1).build());indexQueryList.add(new IndexQueryBuilder().withObject(product2).build());indexQueryList.add(new IndexQueryBuilder().withObject(product3).build());// 批量添加文檔elasticsearchRestTemplate.createIndex(Product.class); // 創(chuàng)建索引庫elasticsearchRestTemplate.putMapping(Product.class); // 創(chuàng)建映射關系elasticsearchRestTemplate.bulkIndex(indexQueryList, IndexCoordinates.of("product"));
}

在這里插入圖片描述

4、聚合查詢(terms、sum)

/*** 測試聚合查詢*/
@Test
public void testAggs() {// 構造聚合查詢對象AbstractAggregationBuilder aggregationBuilder = AggregationBuilders// 分組查詢,size=2表示查詢前兩個分組.terms("group_category").field("category").size(2)// 子聚合查詢.subAggregation(AggregationBuilders.sum("sum_price").field("price"));// 構造NativeSearchQuery條件查詢對象NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery()) // 設置查詢條件.addAggregation(aggregationBuilder) // 設置聚合查詢參數(shù)// 各種查詢條件.....build();// 調用search方法進行查詢SearchHits<Product> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);// 解析聚合結果Aggregations aggregations = searchHits.getAggregations();// 根據(jù)名稱獲取聚合結果Terms terms = aggregations.get("group_category");// 獲取桶List<? extends Terms.Bucket> buckets = terms.getBuckets();// 遍歷for (Terms.Bucket bucket : buckets) {//  獲取分組的keyString key = bucket.getKeyAsString();// 獲取文檔數(shù)量long docCount = bucket.getDocCount();//獲取子聚合結果Sum sumPrice = bucket.getAggregations().get("sum_price");double value = sumPrice.getValue();System.out.println("分組名稱: " + key);System.out.println("文檔個數(shù): " + docCount);System.out.println("總價格: " + value);System.out.println("----------------------");}
}

在這里插入圖片描述在這里插入圖片描述


3.5 使用ElasticsearchRepository接口操作ES


ElasticsearchRepository接口常用方法:

  • 保存單個文檔:void save(T entity)
  • 保存多個文檔:Iterable<T> saveAll(Iterable<T> entities)
  • 根據(jù) ID 獲取文檔:Optional<T> findById(String id)
  • 判斷文檔是否存在:Boolean existsById(String id)
  • 獲取所有文檔:Iterable<T> findAll()
    • 方法參數(shù):Sort :自定義排序
    • 方法參數(shù):Pageable:分頁對象
  • 獲取多個ID 的文檔:Iterable<T> findAllById(Iterable<String> ids)
  • 獲取文檔數(shù)量:long count()
  • 刪除單個文檔:void deleteById(String id)
  • 刪除多個文檔:void deleteAll(Iterable<? extends T> entities)
  • 刪除所有文檔:void deleteAll()
  • 條件查詢:search()

定義持久層接口:

package cn.aopmin.dao;import cn.aopmin.pojo.Product;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;/*** 自定義接口去繼承ElasticsearchRepository接口,實現(xiàn)對ES的操作* ElasticsearchRepository<Product, Long>  Product:實體類 Long:主鍵類型*/
@Repository
public interface ProductRepository extends ElasticsearchRepository<Product, Long> {}

示例1:根據(jù)文檔id查文檔(findById)

package cn.aopmin.test;import cn.aopmin.dao.ProductRepository;
import cn.aopmin.pojo.Product;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.Optional;/*** 測試ElasticsearchRepository接口* @author 白豆五* @version 2023/07/25* @since JDK8*/
@SpringBootTest
public class ElasticsearchRepositoryTest {@Autowiredprivate ProductRepository productRepository; //自定義持久層接口/*** 測試根據(jù)id查詢文檔*/@Testpublic void test() {Optional<Product> optional = productRepository.findById(1L);Product product = optional.get();System.out.println(product);}
}

在這里插入圖片描述


示例2:查詢所有(findAll)

/*** 測試查詢所有文檔*/
@Test
public void testFindAll() {// 查詢所有文檔Iterable<Product> iterable = productRepository.findAll();//  遍歷迭代器對象for (Product product : iterable) {System.out.println(product);}System.out.println("====================================");// 查詢所有,對查詢結果按照price字段進行排序Iterable<Product> iterable2 = productRepository.findAll(Sort.by(Sort.Direction.DESC, "price"));iterable2.forEach(System.out::println);
}

在這里插入圖片描述


示例3:條件查詢(調用search方法,通過QueryBuilders構建查詢條件)

/*** 測試條件查詢*/
@Test
public void testMatchAll(){Iterable<Product> iterable = productRepository.search(QueryBuilders.matchAllQuery());iterable.forEach(System.out::println);
}  

在這里插入圖片描述


示例4:分頁查詢

/*** 測試分頁查詢*/
@Test
public void testPage() {// 分頁對象Pageable Pageable = PageRequest.of(0, 2);// 分頁查詢// productRepository.search(QueryBuilders.matchAllQuery(), Pageable);Page<Product> page = productRepository.findAll(Pageable);// 獲取總記錄數(shù)System.out.println("total:" + page.getTotalElements());// 獲取當前頁碼System.out.println("當前頁碼:" + (page.getNumber() + 1));// 獲取總頁數(shù)System.out.println("總頁數(shù):" + page.getTotalPages());// 獲取當前頁數(shù)據(jù)page.forEach(System.out::println);
}

在這里插入圖片描述


示例5:自定義查詢方法(findByXxx)

Spring Data 支持自定義查詢方法,但是方法命名需要遵循一定的命名規(guī)范,這樣SpringData框架才會根據(jù)方法名自動實現(xiàn)相關查詢操作。

比如:findByName,表示根據(jù)字段name進行查詢,它會自動幫你完成,無需寫實現(xiàn)類。

方法命名規(guī)范:(參考:https://blog.csdn.net/hzj_java/article/details/118096157)

在這里插入圖片描述

① 在持久層接口中定義方法(方法名會自動提示)

@Repository
public interface ProductRepository extends ElasticsearchRepository<Product, Long> {// 查詢指定價格區(qū)間的文檔public Iterable<Product> findByPriceBetween(Double begin, Double end);
}

②測試

/*** 測試自定義查詢*/
@Test
public void testFindByPriceBetween() {Iterable<Product> iterable = productRepository.findByPriceBetween(1000.0, 3000.0);iterable.forEach(System.out::println);
}

在這里插入圖片描述

小節(jié):

操作es有兩種技術方案:

方案一:使用原生API(RestHighLevelClient),可以更靈活地操作Elasticsearch。(底層代碼)

方案二:使用Spring Data Elasticsearch,可以通過ElasticsearchRestTemplate和ElasticsearchRepository 接口操作ES。

  • ElasticsearchRestTemplate
  • ElasticsearchRepository 接口
    • 使用默認的crud方法
    • 自定義查詢方法 findByXxx
http://www.risenshineclean.com/news/9040.html

相關文章:

  • 網頁設計汽車網站建設在線視頻用什么網址
  • 珠海網站制作平臺今日重大財經新聞
  • 達人設計網官方網站seo排名優(yōu)化首頁
  • 自助建站門戶網站優(yōu)化網站做什么的
  • 高中畢業(yè)學網站開發(fā)廣州google推廣
  • 有個專門做gif的網站怎么查看域名是一級還是二級域名
  • 怎么設計網站頁面地推團隊聯(lián)系方式
  • 專業(yè)的贛州網站建設武漢seo網站推廣
  • 網站建設盒子怎么搭建網站廣告策劃
  • 公司做網站花銷會計分錄發(fā)稿推廣
  • 南寧建站模板展示西安seo外包行者seo
  • 網站建哪家好app拉新
  • 查詢建設銀行卡卡號網站西安百度網站快速排名
  • 網站公司建設市場營銷策劃包括哪些內容
  • 房地產開發(fā)公司網站源碼優(yōu)化師的工作內容
  • 網站建設中的咨詢服務申京效率值聯(lián)盟第一
  • DW做網站的步驟網絡營銷的概念和特征
  • 洪洞網站建設易觀數(shù)據(jù)
  • wordpress 添加文章屬性武漢seo招聘
  • 軟件商店軟件下載蘇州網絡推廣seo服務
  • 沈陽網站開發(fā)外包網絡推廣網站有哪些
  • 杭州免費建站學大教育培訓機構電話
  • 淫穢色情網站境外的成都今天重大新聞事件
  • 重慶江津區(qū)建設委員會官方網站人際網絡營銷2900
  • 塘沽建設網站社交網絡推廣方法
  • 電商網站建設模型圖本溪seo優(yōu)化
  • 有什么ae做動圖的網站百度快速排名軟件
  • 商務網站主頁設計公司營銷團隊外包
  • 做誘導網站關鍵詞挖掘查詢工具
  • 寶安高端網站設計怎么樣百度收錄情況查詢