Elasticsearch作為當前最流行的開源搜索和分析引擎,廣泛應用于日志分析、全文搜索、業務智能等領域。Elasticsearch是一個基于 Apache Lucene 構建的分布式搜索和分析引擎、可擴展數據存儲和矢量數據庫。它針對生產級工作負載的速度和相關性進行了優化。使用 Elasticsearch 可以近乎實時地搜索、索引、存儲和分析各種類型和大小的數據。Kibana是 Elasticsearch 的圖形用戶界面。它是一款強大的工具,可用于可視化和分析數據,以及管理和監控 Elastic Stack。本文將帶你系統學習Elasticsearch的核心概念和基本用法。
一、Elasticsearch基礎概念
在開始實際操作前,我們需要了解幾個核心概念:
- 文檔(Document)
- ES是面向文檔的,文檔是所有可搜索數據的最小單元
- 文檔會被序列化成JSON格式存儲
- 每個文檔都有唯一ID,可自定義或自動生成
- 支持數組和嵌套結構
- 索引(Index)
- 相當于MySQL中的數據庫
- 名稱必須全部小寫
- 包含mapping(定義字段類型)和setting(定義數據分布)
- 節點(Node)與分片(Shard)
- 節點:是 一個ES實例,本質是一個Java進程
- Master Eligible節點:參與選主,管理集群狀態
- Data節點:存儲數據
- Coordinating節點:接收客戶端請求
- 節點的名稱可以通過配置文件配置,或者在啟動的時候使用-E node.name=ropledata指定,默認是隨機分配的。建議咱們自己指定,因為節點名稱對于管理目的很重要,咱們可以通過節點名稱確定網絡中的哪些服務器對應于ES集群中的哪些節點;
- 分片:將索引水平拆分為多個部分
- 主分片數在創建索引時指定,后續不能修改
- 副本分片提供高可用性,可動態調整數量
- 節點:是 一個ES實例,本質是一個Java進程
- 類型:就相當于MySql里的表,我們知道MySql里一個庫下可以有很多表,最原始的時候ES也是這樣,一個索引下可以有很多類型,但是從6.0版本開始,type已經被逐漸廢棄,但是這時候一個索引仍然可以設置多個類型,一直到7.0版本開始,一個索引就只能創建一個類型了(_doc)。 Elasticsearch7 去掉 tpye 概念ES7.x 版本:URL 中的 type 參數為可選。 ES8.x 版本:不?持 URL 中的 type 參數
注意:雖然在實際存儲上,文檔存在于某個索引里,但是文檔必須被賦予一個索引下的
二、什么是倒排索引?
倒排索引(Inverted Index)是搜索引擎最核心的數據結構,也是Elasticsearch實現高效全文搜索的基礎。它與我們熟悉的傳統"正排索引"形成鮮明對比:
- 正排索引(正向索引):文檔文檔(Document)
- ES是面向文檔的,文檔是所有可搜索數據的最小單元
- 文檔會被序列化成JSON格式存儲
- 每個文檔都有唯一ID,可自定義或自動生成
- 支持數組和嵌套結構
- 索引(Index)
- 相當于MySQL中的數據庫
- 名稱必須全部小寫
- 包含mapping(定義字段類型)和setting(定義數據分布)
- 節點(Node)與分片(Shard)
- 節點:一個ES實例,本質是一個Java進程
- Master Eligible節點:參與選主,管理集群狀態
- Data節點:存儲數據
- Coordinating節點:接收客戶端請求
- 分片:將索引水平拆分為多個部分
- 主分片數在創建索引時指定,后續不能修改
- 副本分片提供高可用性,可動態調整數量
- 節點:一個ES實例,本質是一個Java進程
- → 包含的詞
- 類似書籍的目錄,通過章節找內容
- 如:文檔1包含"大話"、"西游"
- 倒排索引(反向索引):詞 → 出現的文檔
- 類似書籍的索引頁,通過關鍵詞找章節
- 如:"西游" → 文檔1、文檔2、文檔3...
三、倒排索引的構建過程
3.1 原始數據示例
以電影片名為例:
文檔ID | 電影名稱 |
1 | 大話西游 |
2 | 大話西游外傳 |
3 | 解析大話西游 |
4 | 西游降魔外傳 |
5 | 夢幻西游獨家解析 |
3.2 分詞處理
中文需要先進行分詞(使用分詞器將句子拆分為詞語):
- "大話西游" → ["大話", "西游"]
- "大話西游外傳" → ["大話", "西游", "外傳"]
- "解析大話西游" → ["解析", "大話", "西游"]
- "西游降魔外傳" → ["西游", "降魔", "外傳"]
- "夢幻西游獨家解析" → ["夢幻", "西游", "獨家", "解析"]
3.3 構建倒排列表
對分詞結果進行反向記錄:
詞項 | 文檔ID列表(Posting List) | 其他信息(如詞頻、位置等) |
西游 | 1,2,3,4,5 | 在1中出現1次,在2中出現1次... |
大話 | 1,2,3 | 在1中出現1次,在2中出現1次... |
外傳 | 2,4 | 在2中出現1次,在4中出現1次... |
解析 | 3,5 | 在3中出現1次,在5中出現1次... |
降魔 | 4 | 在4中出現1次 |
夢幻 | 5 | 在5中出現1次 |
獨家 | 5 | 在5中出現1次 |
三、倒排索引的搜索過程
3.1 搜索示例:查詢"獨家大話西游"
- 查詢分詞:
- "獨家大話西游" → ["獨家", "大話", "西游"]
- 查找倒排列表:
- "獨家" → 文檔5
- "大話" → 文檔1,2,3
- "西游" → 文檔1,2,3,4,5
- 合并結果:
- 文檔1:包含"大話"、"西游"
- 文檔2:包含"大話"、"西游"
- 文檔3:包含"大話"、"西游"
- 文檔5:包含"獨家"、"西游"
- 文檔4:只包含"西游"
相關性評分(簡化版):
評分公式:
得分 = 命中詞數 / 文檔總詞數
-
-
文檔1:命中2詞("大話"、"西游"),總詞數2 → 2/2=1.0
-
文檔2:命中2詞,總詞數3 → 2/3≈0.67
-
文檔3:命中2詞,總詞數3 → 2/3≈0.67
-
文檔5:命中2詞("獨家"、"西游"),總詞數4 → 2/4=0.5
-
文檔4:命中1詞("西游"),總詞數3 → 1/3≈0.33
-
結果排序:
1. 大話西游 (1.0)
2. 大話西游外傳 (0.67)
3. 解析大話西游 (0.67)
4. 夢幻西游獨家解析 (0.5)
5. 西游降魔外傳 (0.33)
基礎操作
索引管理?
// 創建索引
PUT /ropledata
{"settings": {"number_of_shards": "2","number_of_replicas": "3"}
}// 刪除索引
DELETE /ropledata// 修改副本數
PUT ropledata/_settings
{"number_of_replicas": "2"
}
什么是映射?
映射(Mapping)是ElasticSearch中用于定義文檔及其包含字段如何存儲和索引的機制。它相當于關系型數據庫中的表結構定義,決定了:
- 哪些字段應該被當作全文檢索字段
- 哪些字段包含數字、日期或地理位置信息
- 日期值的格式
- 自定義規則來控制動態添加字段的映射
映射的核心作用
- 字段類型定義:指定每個字段的數據類型(如text、keyword、integer等)
- 索引控制:決定字段是否被索引(可搜索)
- 分析器配置:指定文本字段使用的分詞器
- 格式設置:如日期字段的格式
- 多字段支持:一個字段可以有不同的索引方式
映射類型
1. 顯式映射
單級屬性映射?
用戶明確定義字段的映射規則:
PUT /my-index
{"mappings": {"properties": {"age": { "type": "integer" }, "email": { "type": "keyword" },"name": { "type": "text" }}}
}
多級屬性映射?
PUT /my-index
{"mappings": {"properties": {"age": { "type": "integer" },"email": { "type": "keyword" },"name": { "type": "text" },"address": {"type": "nested","properties": {"street": { "type": "text" },"city": { "type": "keyword" },"zipcode": { "type": "keyword" },"coordinates": {"type": "object","properties": {"lat": { "type": "float" },"lon": { "type": "float" }}}}},"skills": {"type": "nested","properties": {"name": { "type": "keyword" },"level": { "type": "integer" },"certifications": {"type": "nested","properties": {"name": { "type": "text" },"year": { "type": "short" }}}}},"employment_history": {"type": "nested","properties": {"company": { "type": "keyword" },"position": { "type": "text" },"duration_months": { "type": "integer" }}}}}
}
這個映射定義包含:
- 基本字段:age(integer), email(keyword), name(text)
- 嵌套地址對象:包含街道(text)、城市(keyword)、郵編(keyword)和坐標對象
- 嵌套技能數組:包含技能名(keyword)、等級(integer)和嵌套的認證數組
- 嵌套工作經歷數組:包含公司(keyword)、職位(text)和持續時間(integer)
所有嵌套關系都使用?"type": "nested"?來確保數組中的對象被獨立索引和查詢。
2. 動態映射
當索引新文檔時,ES會自動檢測并添加新字段:
PUT /my-index/_doc/1
{"age": 25,"email": "user@example.com","name": "John Doe"
}
ES會自動推斷:
age → long
email → keyword
name → text
常用字段類型
類型 | 說明 |
text | 全文檢索字段,會被分詞 |
keyword | 精確值字段,不分析,用于過濾、排序和聚合 |
long/integer | 長整型/整型數值 |
double/float | 雙精度/單精度浮點數 |
date | 日期類型,可指定格式 |
boolean | 布爾值 |
object | JSON對象 |
nested | 嵌套對象,保持數組中對象的獨立性 |
geo_point | 經緯度坐標 |
映射操作示例
查看映射
GET /my-index/_mapping
添加新字段映射
PUT /my-index/_mapping
{"properties": {"employee-id": {"type": "keyword","index": false}}
}
更新映射注意事項
重要:已存在字段的映射類型不能直接修改,必須:
- 創建新索引并定義新映射
- 使用_reindex API遷移數據
POST _reindex
{"source": { "index": "old-index" },"dest": { "index": "new-index" }
}
映射參數詳解
常用參數
- index:是否索引該字段(true/false)
- analyzer:指定文本分析器
- search_analyzer:指定搜索時分析器
- format:日期格式(如"yyyy-MM-dd")
- copy_to:將字段值復制到目標字段
- fields:多字段特性,允許一個字段有多種索引方式
多字段示例
{"mappings": {"properties": {"city": {"type": "text","fields": {"raw": { "type": "keyword"}}}}}
}
這樣city
可以用于全文搜索,city.raw
可用于精確匹配和聚合。
索引數據
- 預先定義映射:生產環境建議預先定義映射,避免動態映射的不確定性
- 合理使用keyword:不需要分詞的字段應設為keyword類型
- 控制動態映射:可通過
dynamic
參數控制(true/false/strict) - 避免頻繁修改:映射特別是字段類型不宜頻繁變更
- 使用別名:便于重建索引時無縫切換映射是ElasticSearch高效工作的基礎,合理的映射設計能顯著提升搜索性能和結果的準確性。
一、數據插入操作
1. 不指定文檔ID插入
Elasticsearch 會自動生成唯一ID
POST /ropledata/_doc/
{"id":1,"name":"且聽_風吟","page":"https://ropledata.blog.csdn.net","say":"歡迎點贊,收藏,關注,一起學習"
}
2. 指定文檔ID插入
適用于需要自定義ID的場景
POST /ropledata/_doc/101
{"id":1,"name":"且聽_風吟","page":"https://ropledata.blog.csdn.net","say":"歡迎點贊,收藏,關注,一起學習"
}
二、數據刪除操作
刪除指定ID的文檔:
DELETE /ropledata/_doc/101
三、數據更新操作
1. 全局更新(覆蓋更新)
會完全替換原有文檔內容
PUT /ropledata/_doc/101
{"id":1,"name":"且聽_風吟","page":"https://ropledata.blog.csdn.net","say":"再次歡迎點贊,收藏,關注,一起學習"
}
2. 局部更新
只更新指定字段,性能優于全局更新
POST /ropledata/_update/101
{"doc": {"say":"奧力給"}
}
四、數據查詢操作
1. 基礎查詢(默認返回10條)
GET /ropledata/_search
2. 帶條件的全局查詢
POST /ropledata/_search
{"query": {"match_all": {}},"sort": [{"id": {"order": "asc"}}]
}
五、索引重建操作
POST _reindex
{"source": { "index": "twitter" },"dest": { "index": "new_twitter" }
}
關鍵知識點總結
- 插入數據:
- 不指定ID時ES自動生成
- 指定ID適用于業務關聯場景
- 更新機制:
- ES文檔不可變,更新實質是新版本覆蓋舊版本
- 局部更新(
_update
)比全局更新(PUT
)性能更好
- 查詢特點:
- 默認返回10條結果
- 可通過
sort
參數控制排序 match_all
查詢全部文檔
- 版本兼容性:
- 本文示例適用于Elasticsearch 7.x版本
- 6.x及以下版本語法可能有差異
- 性能建議:
- 頻繁更新的字段考慮單獨索引
- 大文檔更新優先使用局部更新
提示:在實際開發中,建議結合業務場景選擇合適的操作方式,批量操作(Bulk API)能顯著提高大批量數據處理的效率。