Elasticsearch 講解及 Java 應用實戰:從入門到落地

在數據量爆炸的今天,傳統數據庫的查詢能力越來越難以滿足復雜的檢索需求。比如電商平臺的商品搜索,需要支持關鍵詞模糊匹配、多條件篩選、熱門度排序等功能,這時候 Elasticsearch(簡稱 ES)就成了最佳選擇。作為一款分布式全文搜索引擎,ES 以其強大的檢索能力、靈活的擴展性被廣泛應用。本文將從 ES 核心概念講起,結合 Java 實戰案例,帶你快速掌握 ES 的應用技巧。

一、Elasticsearch 核心概念與優勢

在使用 ES 前,我們需要先理清它的核心概念 —— 很多人會把 ES 和數據庫類比,這個思路其實很實用。

1.1 ES 與關系型數據庫的概念對應

如果把 ES 比作數據庫,兩者的核心概念可以這樣對應:

關系型數據庫

Elasticsearch

說明

Database(數據庫)

Index(索引)

一個索引對應一類數據集合,比如 “商品索引”“用戶索引”

Table(表)

Type(類型)

早期 ES 用于區分索引內的不同數據類型,7.x 后已廢棄,一個索引只對應一種類型

Row(行)

Document(文檔)

索引中的一條數據,以 JSON 格式存儲

Column(列)

Field(字段)

文檔中的一個屬性,比如商品的 “名稱”“價格”

Schema(表結構)

Mapping(映射)

定義文檔中字段的類型、分詞器等規則

1.2 ES 的核心優勢

相比傳統數據庫和其他搜索引擎,ES 的核心競爭力體現在這幾點:

  • 全文檢索能力:支持關鍵詞分詞、模糊匹配、同義詞擴展等,比如搜索 “手機” 時能匹配 “智能手機”“移動電話”。
  • 分布式架構:天然支持分片和副本,數據自動分片存儲,副本保證高可用,可輕松擴展至海量數據。
  • 近實時搜索:數據寫入后秒級可查,兼顧實時性和性能。
  • 靈活的聚合分析:支持統計、排序、分組等復雜分析,比如按 “商品分類” 統計銷量 Top10。

二、Elasticsearch 核心操作入門

要使用 ES,首先要掌握其基礎操作。ES 提供 RESTful API 接口,可通過 HTTP 請求直接操作,也可通過客戶端工具(如 Kibana 的 Dev Tools)執行。

2.1 索引相關操作

(1)創建索引及映射

創建一個 “商品索引”,并定義字段映射(類似數據庫建表時定義字段類型):

# 創建商品索引

PUT /product_index

{

"mappings": {

"properties": {

"id": { "type": "keyword" }, // 商品ID,精確匹配,不分詞

"name": {

"type": "text",

"analyzer": "ik_max_word", // 使用IK分詞器(中文分詞必備)

"fields": {

"keyword": { "type": "keyword" } // 用于精確查詢或排序

}

},

"price": { "type": "double" }, // 價格

"category": { "type": "keyword" }, // 分類,精確匹配

"createTime": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" } // 創建時間

}

}

}

這里有兩個關鍵注意點:

  • text 與 keyword:text類型用于全文檢索(會分詞),keyword用于精確匹配(不分詞),同一個字段可通過fields同時支持兩種類型。
  • 中文分詞:必須使用 IK 分詞器(需提前安裝),ik_max_word會將文本拆分為最細粒度(如 “華為手機” 拆為 “華為”“手機”),ik_smart為粗粒度拆分。
(2)查看索引映射

GET /product_index/_mapping

(3)刪除索引

DELETE /product_index

2.2 文檔相關操作

文檔是 ES 中最小的數據單元,所有操作圍繞文檔展開。

(1)新增文檔

# 新增文檔(指定ID)

PUT /product_index/_doc/1001

{

"id": "1001",

"name": "華為Mate 60 Pro 智能手機",

"price": 6999.00,

"category": "手機",

"createTime": "2024-01-15 09:30:00"

}

# 新增文檔(自動生成ID)

POST /product_index/_doc

{

"id": "1002",

"name": "蘋果iPhone 15 手機",

"price": 7999.00,

"category": "手機",

"createTime": "2024-01-20 14:20:00"

}

(2)查詢文檔

ES 的查詢能力非常強大,這里列舉幾種常用場景:

  • 精確查詢(根據分類查詢手機商品):

GET /product_index/_search

{

"query": {

"term": {

"category": { "value": "手機" }

}

}

}

  • 全文檢索(搜索包含 “華為” 的商品):

GET /product_index/_search

{

"query": {

"match": {

"name": "華為"

}

}

}

  • 組合條件查詢(價格在 5000-8000,且分類為手機):

GET /product_index/_search

{

"query": {

"bool": {

"must": [

{ "term": { "category": "手機" } },

{ "range": { "price": { "gte": 5000, "lte": 8000 } } }

]

}

},

"sort": [{"createTime": "desc"}], // 按創建時間倒序

"from": 0, "size": 10 // 分頁(從第0條開始,取10條)

}

(3)更新與刪除文檔
  • 更新文檔(全量更新或局部更新):

# 局部更新(只更新價格)

POST /product_index/_update/1001

{

"doc": {

"price": 6799.00

}

}

  • 刪除文檔

DELETE /product_index/_doc/1001

三、Java 操作 Elasticsearch 實戰

實際開發中,我們很少直接調用 REST API,而是通過官方客戶端工具操作。ES 官方推薦的 Java 客戶端是 Elasticsearch Java Client(7.x 后替代了舊的 Transport Client)。

3.1 環境準備

(1)引入依賴

在 Maven 項目的pom.xml中添加依賴(版本需與 ES 服務器一致,這里以 8.10.4 為例):

<dependencies>

<!-- Elasticsearch Java Client -->

<dependency>

<groupId>co.elastic.clients</groupId>

<artifactId>elasticsearch-java</artifactId>

<version>8.10.4</version>

</dependency>

<!-- 依賴Jackson處理JSON -->

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-databind</artifactId>

<version>2.15.2</version>

</dependency>

<!-- 連接池 -->

<dependency>

<groupId>org.apache.httpcomponents.client5</groupId>

<artifactId>httpclient5</artifactId>

<version>5.3</version>

</dependency>

</dependencies>

(2)初始化客戶端

創建 ES 客戶端連接(類似數據庫連接池):

import co.elastic.clients.elasticsearch.ElasticsearchClient;

import co.elastic.clients.json.jackson.JacksonJsonpMapper;

import co.elastic.clients.transport.ElasticsearchTransport;

import co.elastic.clients.transport.rest_client.RestClientTransport;

import org.apache.http.HttpHost;

import org.elasticsearch.client.RestClient;

public class EsClient {

// 單例客戶端

private static ElasticsearchClient client;

static {

// 創建REST客戶端(連接ES服務器,可配置多個節點)

RestClient restClient = RestClient.builder(

new HttpHost("localhost", 9200, "http")

).build();

// 創建傳輸層

ElasticsearchTransport transport = new RestClientTransport(

restClient, new JacksonJsonpMapper()

);

// 創建客戶端

client = new ElasticsearchClient(transport);

}

public static ElasticsearchClient getClient() {

return client;

}

}

注意:ES 客戶端版本必須與服務器版本保持一致,否則可能出現兼容性問題。

3.2 核心操作實戰:商品搜索功能

以 “電商商品搜索” 為例,實現文檔新增、條件查詢、分頁排序等核心功能。

(1)定義商品實體類

import com.fasterxml.jackson.annotation.JsonFormat;

import lombok.Data;

import java.util.Date;

@Data

public class Product {

private String id;

private String name;

private Double price;

private String category;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")

private Date createTime;

}

(2)新增商品文檔

import co.elastic.clients.elasticsearch.ElasticsearchClient;

import co.elastic.clients.elasticsearch.core.IndexRequest;

import co.elastic.clients.elasticsearch.core.IndexResponse;

import java.io.IOException;

public class ProductService {

private final ElasticsearchClient client = EsClient.getClient();

// 新增商品到ES

public void addProduct(Product product) throws IOException {

// 構建索引請求(指定索引名、文檔ID和數據)

IndexRequest<Product> request = IndexRequest.of(b -> b

.index("product_index") // 索引名

.id(product.getId()) // 文檔ID(可選,不指定則自動生成)

.document(product) // 文檔數據

);

// 執行請求

IndexResponse response = client.index(request);

System.out.println("新增結果:" + response.result());

}

}

(3)多條件查詢商品

實現一個帶條件、分頁、排序的商品搜索功能:

import co.elastic.clients.elasticsearch.core.SearchRequest;

import co.elastic.clients.elasticsearch.core.SearchResponse;

import co.elastic.clients.elasticsearch.core.search.Hit;

import co.elastic.clients.elasticsearch.core.search.TotalHits;

import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

public class ProductService {

// ... 其他代碼省略

/**

* 搜索商品

* @param keyword 關鍵詞(搜索商品名稱)

* @param category 分類(可選)

* @param minPrice 最低價格(可選)

* @param maxPrice 最高價格(可選)

* @param page 頁碼(從1開始)

* @param size 每頁條數

* @return 商品列表及總條數

*/

public SearchResult<Product> searchProducts(String keyword, String category,

Double minPrice, Double maxPrice,

int page, int size) throws IOException {

// 構建查詢條件

SearchRequest request = SearchRequest.of(b -> b

.index("product_index") // 指定索引

.query(q -> q

.bool(bool -> {

// 拼接查詢條件

if (keyword != null && !keyword.isEmpty()) {

// 全文檢索商品名稱

bool.must(m -> m.match(t -> t.field("name").query(keyword)));

}

if (category != null && !category.isEmpty()) {

// 精確匹配分類

bool.filter(f -> f.term(t -> t.field("category").value(category)));

}

if (minPrice != null || maxPrice != null) {

// 價格范圍過濾

bool.filter(f -> f.range(r -> {

if (minPrice != null) r.gte(minPrice);

if (maxPrice != null) r.lte(maxPrice);

return r.field("price");

}));

}

return bool;

})

)

.sort(s -> s.field(f -> f.field("createTime").order("desc"))) // 按創建時間倒序

.from((page - 1) * size) // 起始位置(分頁)

.size(size) // 每頁條數

);

// 執行查詢

SearchResponse<Product> response = client.search(request, Product.class);

// 處理結果

List<Product> products = new ArrayList<>();

for (Hit<Product> hit : response.hits().hits()) {

products.add(hit.source()); // 獲取文檔數據

}

// 總條數

TotalHits totalHits = response.hits().total();

long total = 0;

if (totalHits != null && totalHits.relation() == TotalHitsRelation.Eq) {

total = totalHits.value();

}

return new SearchResult<>(total, products);

}

// 定義結果封裝類

@Data

public static class SearchResult<T> {

private long total; // 總條數

private List<T> data; // 數據列表

public SearchResult(long total, List<T> data) {

this.total = total;

this.data = data;

}

}

}

這個方法包含了 ES 查詢的核心場景:

  • 多條件組合:用bool查詢拼接 “必須滿足(must)” 和 “過濾(filter)” 條件;
  • 全文檢索:match查詢用于商品名稱的關鍵詞搜索;
  • 精確匹配與范圍過濾:term查詢匹配分類,range查詢過濾價格;
  • 分頁與排序:通過from、size實現分頁,sort指定排序規則。

3.3 性能優化技巧

在實際應用中,ES 的性能優化不可忽視,尤其是數據量大或查詢頻繁的場景:

  1. 合理設計映射
    • 不需要檢索的字段設置index: false(如商品詳情的大文本);
    • 精確匹配字段用keyword類型,避免text類型的不必要分詞。
  1. 優化查詢語句
    • 用filter代替must(filter不計算評分,且可緩存結果);
    • 避免wildcard前綴匹配(如name:*手機),會導致全表掃描;
    • 分頁查詢時,深分頁(如from:10000)改用search_after。
  1. 索引分片優化
    • 初始分片數設置為 “節點數 ×1~3”(如 3 個節點可設 5 個分片);
    • 分片大小控制在 20GB~50GB 之間,過大影響查詢性能。
  1. 批量操作

// 批量新增示例

BulkRequest.Builder bulk = new BulkRequest.Builder();

for (Product product : productList) {

bulk.operations(op -> op

.index(idx -> idx

.index("product_index")

.id(product.getId())

.document(product)

)

);

}

client.bulk(bulk.build());

    • 批量新增 / 更新用BulkRequest,減少網絡請求次數;

四、常見問題與解決方案

在 ES 應用中,新手容易遇到一些 “坑”,這里總結幾個高頻問題:

  1. 中文分詞效果差
    • 原因:未安裝 IK 分詞器,默認分詞器會把中文拆成單字;
    • 解決:在 ES 插件目錄安裝 IK 分詞器(版本與 ES 一致),并在映射中指定analyzer: "ik_max_word"。
  1. 查詢結果與預期不符
    • 檢查字段類型:如果用term查詢text類型字段,可能因分詞導致匹配失敗(需用match查詢);
    • 檢查分詞結果:通過GET /product_index/_analyze測試字段分詞效果。
  1. 寫入 / 查詢性能慢
    • 寫入慢:檢查分片副本數(初期可設 1 個副本)、是否開啟批量寫入;
    • 查詢慢:查看是否命中索引(通過explain分析查詢計劃)、是否需要增加節點或優化分片。

五、總結

Elasticsearch 是一款強大的搜索引擎,其核心價值在于全文檢索分布式擴展能力。本文從基礎概念出發,通過 “理論 + 實戰” 的方式講解了 ES 的核心操作,并結合 Java 案例實現了商品搜索功能。

要熟練掌握 ES,關鍵在于:

  1. 理解索引、文檔、映射等核心概念,明確text與keyword的區別;
  1. 掌握bool組合查詢、范圍查詢、聚合分析等核心語法;
  1. 結合實際場景優化映射設計和查詢語句,避免性能問題。

如果你在 ES 應用中遇到過特殊場景(如大數據量同步、復雜聚合分析),歡迎在評論區分享你的解決方案!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/916192.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/916192.shtml
英文地址,請注明出處:http://en.pswp.cn/news/916192.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

docker pull weaviate 國內拉取失敗的問題

我是校內網&#xff0c;嘗試了 改鏡像源 (cooragent) ruiyCJQ:~/sdb/B/cooragent$ sudo vim /etc/docker/daemon.json [sudo] password for ruiy: (cooragent) ruiyCJQ:~/sdb/B/cooragent$ sudo service docker restart (cooragent) ruiyCJQ:~/sdb/B/cooragent$ sudo docke…

Vue項目使用Univer Sheets

Univer Excel主頁鏈接&#xff1a;安裝步驟 1. 安裝 使用預設模式的包管理器安裝 - 預設模式&#xff1a;可以理解為開包即用的模式&#xff0c;省去很多配置&#xff0c;當然自由度不如插件模式 pnpm add univerjs/presets univerjs/preset-sheets-core2. 前端代碼 <te…

Python day24

浙大疏錦行 python day24 內容&#xff1a; 元組&#xff1a;類比于列表&#xff0c;不過元組的元素不能被修改&#xff0c;顯示也是從[]改為了()&#xff0c;其余操作則是和列表類似&#xff0c;且元組是有序的可迭代對象&#xff1a;即可以使用迭代器訪問的對象&#xff0c…

Three.js 動畫系統入門:Tween.js 與 AnimationMixer 的使用

引言 動畫是 Three.js 中增強 3D 場景動態效果的核心技術&#xff0c;能夠為用戶帶來沉浸式體驗。Three.js 支持通過 Tween.js 實現簡單的屬性動畫&#xff0c;以及通過 AnimationMixer 處理復雜的混合動畫和骨骼動畫。本文將深入探討如何使用 Tween.js 控制 Object3D 的屬性動…

裝修進度管理系統功能對比:主流工具9選

本文分享了9款常用的裝修進度管理軟件&#xff0c;包括&#xff1a;1.Worktile&#xff1b;2.中望軟件&#xff1b;3.三維家&#xff1b;4.Procore&#xff1b;5.易達裝修管理系統&#xff1b;6.裝修管家&#xff1b;7.Zoho Projects&#xff1b;8.中建君聯&#xff1b;9.一品裝…

深度學習篇---預訓練模型

在深度學習中&#xff0c;預訓練模型&#xff08;Pretrained Model&#xff09; 是提升開發效率和模型性能的 “利器”。無論是圖像識別、自然語言處理還是語音識別&#xff0c;預訓練模型都被廣泛使用。下面從概念、使用原因、場景、作用等方面詳細介紹&#xff0c;并結合 Pyt…

Redis ①⑦-分布式鎖

分布式鎖 分布式鎖是鎖的一種&#xff0c;都是為了解決多線程/多進程環境下&#xff0c;對共享資源的訪問沖突問題。 不過&#xff0c;像 Java 的 synchronized 或者 C 的 mutex 這種鎖&#xff0c;都是進程內的鎖&#xff0c;而分布式鎖則是跨越進程/機器的鎖。也就是可以針對…

OpenCV-圖像預處理?【圖像顏色空間轉換、灰度化實驗、二值化處理、鏡像翻轉 和 仿射變換】

文章目錄先言一、圖像顏色空間轉換1.RGB顏色空間2.顏色加法3.顏色加權加法4.HSV顏色空間5.圖像轉換&#xff08;cvtColor()&#xff09;二、灰度實驗1.灰度圖2.圖像灰度化&#xff08;最大值法&#xff09;3.圖像灰度化&#xff08;平均值法&#xff09;4.圖像灰度化&#xff0…

APP逆向 day9 安卓開發基礎

一.前言 app逆向當然要學安卓基礎啦&#xff01;今天我們來教安卓基礎當然&#xff0c;安卓基礎不會教的很多&#xff0c;比java還要少&#xff0c;還是那句話&#xff0c;了解就好。 二.安卓環境搭建 2.1 安卓介紹 如果做安卓開發 需要會java代碼安卓SDK(安卓提供的內置…

Jmeter的元件使用介紹:(三)配置元件詳解02

六、計數器 可以用來做一些變量自增操作。 1、Starting value:定義初始值 2、遞增&#xff1a;定義每次執行遞增多少 3、Maximum value:定義承受的最大值 4、數據格式&#xff1a;可以不填&#xff0c;也可以定義成000;001;002等等任意格式都行。&#xff08;1&#xff09;如…

JavaWeb學習打卡15(JSP標簽、JSTL標簽、EL表達式)

EL表達式&#xff1a;${ }獲取數據執行運算獲取web開發的常用對象在pom.xml 文件中導入JSP、JSTL相關依賴&#xff1a;<!--JSP依賴--><!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --><dependency><groupId>java…

7.22數據結構——順序表

文章目錄一、思維導圖二、實現順序表的功能代碼head.htest.cmain.c一、思維導圖 二、實現順序表的功能代碼 head.h #ifndef __HEAD_H__ #define __HEAD_H__#include <stdio.h> #include <string.h> #include <stdlib.h> //數組的最大長度 #define MAXSIZE …

【如何無限制免費試用 IDEA || Pycharm(JB 全家桶)】

如何無限制免費試用 IDEA || Pycharm(JB 全家桶) 一、目標:解決 JB 全家桶試用時長痛點 如果你是程序員,大概率用過 JetBrains 家的 IDE——IDEA 寫 Java、Pycharm 寫 Python、WebStorm 做前端,體驗確實頂流,但官方 30 天試用到期后,動輒幾千的年費實在讓人肉痛。 咱…

Qt(資源庫和按鈕組)

這一節是對上一節的補充&#xff0c;上一節提到QLabel類和QAabstractButton類&#xff0c;這節內容&#xff1a;1.如設置資源庫&#xff0c;使用資源設置圖片2. 使用按鈕組管理多個按鈕。一、資源庫1. 資源庫作用Qt的資源庫&#xff08;Resource System&#xff0c;.qrc文件&am…

一道檢驗編碼能力的字符串的題目

#include<iostream> #include<vector> #include<string> using namespace std; int bNum0,gNum0; int findEnd(string& s,int si){int lens.size();//當前字母在哪個字符串中,存入comp中string comp;if(s[si]b||s[si]o||s[si]y){comp"boy";bNu…

UniApp X 網絡請求避坑指南:從 JS 到 UTS 的 JSON 數據處理全解析

在 UniApp 開發中&#xff0c;我們經常需要通過 uni.request 獲取服務器返回的 JSON 數據&#xff0c;并將其綁定到頁面或進行邏輯處理。但在 UniApp X&#xff08;基于 UTS&#xff09; 中&#xff0c;由于引入了 強類型語言特性&#xff0c;處理 JSON 數據的方式與 JS 有明顯…

iOS 網絡請求常用依賴庫與系統自帶 API 介紹與示例

iOS 網絡請求常用依賴庫與系統自帶 API 介紹與示例 在 iOS 開發中&#xff0c;進行網絡請求是幾乎所有應用都不可或缺的功能。開發者有多種選擇來處理網絡通信&#xff0c;從系統自帶的 URLSession 到各種流行的第三方庫。下面我將為您介紹 URLSession、AFNetworking、Alamofir…

JavaScript 中 let 在循環中的作用域機制解析

一、let在循環中的特殊性 let作為ES6引入的塊級作用域聲明&#xff0c;在循環結構中存在特殊行為&#xff0c;其核心區別于var的函數作用域特性。理解這一特性對于編寫正確的閉包邏輯至關重要。 在 ECMAScript 規范里&#xff0c;let聲明的變量具有塊級作用域特性&#xff0c;這…

@Subscribe@AllowConcurrentEvents解析這兩個注解

@Subscribe@AllowConcurrentEvents解析這兩個注解 @Subscribe 和 @AllowConcurrentEvents 是 Guava EventBus(Google 開源的事件總線框架)中用于處理事件訂閱的注解,主要用于實現組件間的解耦通信。下面分別解析: 1. @Subscribe 注解 作用:標記一個方法為事件訂閱者方法,…

好看的小程序推廣單頁HTML源碼 可用作導航頁

內容目錄一、詳細介紹二、效果展示1.部分代碼2.效果圖展示三、學習資料下載一、詳細介紹 響應式的小程序推廣單頁HTML源碼。這個設計采用了現代化的UI元素&#xff0c;包含吸引人的標題、特性展示、二維碼區域和行動號召按鈕。 二、效果展示 1.部分代碼 代碼如下&#xff0…