ElasticSearch學習

ElasticSearch(中文官網)

之前在蟹老闆手下干命的日子裡,我給公司搭建了一套LEK,收集我們測試環境、生成環境,每個服務運行狀態,以及bug及時定位,現在在新東家ElasticSearch除了做日誌收集,還會保存業務數據文檔,提升查詢效率。

在上次寫的「使用ElasticSearch、Kibana、Docker 進行日誌收集」 介紹了如何進行環境搭建,以及日誌數據收集。

Elasticsearch 基本操作

dev_tools命令執行面板

dev_toolsKibana 提供的命令執行面板,當然大家也會看到其他人使用Postman調用ElasticSearch介面,但是我還是喜歡使用dev_tools(如果安裝了Kibana就可以使用,也可以使用Postman)

索引操作

關於索引操作我列舉了一些常用的api,大家可以根據我給出的文檔連接詳細的閱讀文檔,拋磚引你。

創建索引

索引必須小寫,不支援大寫,重複創建索引會報錯

# 創建索引
PUT /test_dawn
{
  
}

# 返回結果
# 注意:創建索引庫的分片數默認 1 片,在 7.0.0 之前的 Elasticsearch 版本中,默認 5 片
{
  # 【響應結果】true 操作成功
  "acknowledged" : true,
  # 【分片結果】分片操作成功
  "shards_acknowledged" : true,
  # 【索引名稱】
  "index" : "test_dawn"
}

查看所有索引詳細資訊

GET /_cat/indices?v

名稱 含義
health 當前伺服器健康狀態,green(集群完整),yellow(單點正常,集群不完整),red(單點異常)
status 索引打開、關閉
index 索引名
uuid 索引統一編號
pri 主分片數量
rep 副本數量
docs.count 可用文檔數量
docs.deleted 文檔刪除狀態(邏輯刪除)
store.size 主分片和副分片整體占空間大小
pri.store.size 主分片占空間大小

查看單個索引

# 查看test_dawn索引資訊
GET /test_dawn

# 返回參數
{
  # 索引名
  "test_dawn" : {
    # 別名
    "aliases" : { },
    # 映射
    "mappings" : { },
    # 設置
    "settings" : {
      "index" : {
        # 創建時間
        "creation_date" : "1659450485862",
        # 主分片數量
        "number_of_shards" : "1",
        # 副分片數量
        "number_of_replicas" : "1",
        # 唯一標識
        "uuid" : "Gsu7-arFRJmju1p3_5wSOQ",
        "version" : {
          "created" : "7090299"
        },
        # 名稱
        "provided_name" : "test_dawn"
      }
    }
  }
}

刪除索引

刪除不存在的索引會報錯

DELETE /test_dawn

創建映射

提醒:索引不存在會報錯
創建映射就相當於,創建表需要添加欄位、欄位類型的操作(後面講到文檔操作的時候我們也可以直接添加屬性,ElasticSearc會自動推斷我們添加的屬性使用什麼類型)ElasticSearc屬性類型

# 創建映射
PUT /test_dawn/_mapping
{
  "properties":{
    "name": {
      # 支援分詞,但是不支援分組
      "type": "text",
      # 欄位會被索引,則可以用來進行搜索,反之
      "index": true,
      # 是否將數據進行獨立存儲,默認為 false
      "store": false,
      # 分詞器只能在text 類型下使用
      # 指定該屬性使用那個分詞器
      "analyzer": "ik_max_word"
    },
    "age": {
      "type": "integer",
      "index": true,
      "store": false
    },
     "gender": {
      # 不能分詞,數據會作為完整欄位進行匹配,支援分組操作
      "type": "keyword",
      "index": true,
      "store": false
    }
  }
}

查看映射

# 查看映射
GET /test_dawn/_mapping

store_source 對比

默認情況下,欄位值被索引以使它們可搜索,但它們不被存儲。這意味著可以查詢該欄位,但無法檢索原始欄位值。
通常這無關緊要。欄位值已經 是默認存儲的_source欄位的一部分。如果您只想檢索單個欄位或幾個欄位的值,而不是整體_source,則可以通過 源過濾來實現。
在某些情況下,它對一個領域是有意義store的。例如,如果您有一個包含 a title、 adate和一個非常大的content 欄位的文檔,您可能只想檢索 thetitle和 thedate而不必從一個大欄位中提取這些欄位_source

文檔操作

添加文檔

# 添加一個文檔
POST /test_dawn/_doc
{
 "title":"少年說",
 "category":"青春",
 "images":"//baidu.com"
}

# 返回參數
{
  # 索引
  "_index" : "test_dawn",
  # 文檔類型,默認是_doc 在老版中有應用場景,不過到8.0版本就開始淡化、拋棄
  "_type" : "_doc",
  # 文檔唯一id 可以手動指定,或者自動生成
  "_id" : "evQSaYIBhcAYjjJxxtf3",
  # 當前文檔本版,每次對該文檔進行操作會+1
  "_version" : 1,
  # 當前操作類型,還有update
  "result" : "created",
  # 分片
  "_shards" : {
    # 分片總數量
    "total" : 2,
    # 分片成功數量
    "successful" : 1,
    # 分片失敗數量
    "failed" : 0
  },
  "_seq_no" : 2,
  "_primary_term" : 1
}

手動指定Id

查看文檔

# 查看文檔
GET /test_dawn/_doc/1234567890

# 返回參數
{
  "_index" : "test_dawn",
  "_type" : "_doc",
  "_id" : "1234567890",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  # 如果找到了為true
  "found" : true,
  "_source" : {
    "title" : "少年說",
    "category" : "青春",
    "images" : "//baidu.com"
  }
}

修改文檔

剛才我們指定id創建文檔,還有一個作用如果該id 存在就修改文檔(全欄位覆蓋修改)

# 指定id 或者 如果該id 存在就修改文檔(全欄位覆蓋修改)
POST /test_dawn/_doc/1234567890
{
 "title":"少年說",
 "category":"青春"
}

使用該命令一定要注意注意,它是覆蓋式的(工作事小,老婆跑了事大)

指定欄位更新

刪除文檔

# 刪除文檔
DELETE /test_dawn/_doc/1234567890

條件刪除

# 條件刪除
POST /test_dawn/_delete_by_query
{
  "query": {
    "match": {
      "title": "少年說"
    }
  }
}

查詢DSL

Elasticsearch 提供了基於 JSON 的完整 Query DSL(Domain Specific Language)來定義查詢。將查詢 DSL 視為查詢的 AST(抽象語法樹)由兩種類型的子句組成:

  • 葉查詢子句
    葉查詢子句在特定欄位中查找特定值,例如 matchtermrange查詢。這些查詢可以單獨使用。
  • 複合查詢子句
    複合查詢子句包裝其他葉或複合查詢,並用於以邏輯方式組合多個查詢(例如 boolordis_max查詢),或改變它們的行為(例如constant_score查詢)。
    查詢子句的行為不同,具體取決於它們是在 查詢上下文還是過濾器上下文中使用。

允許昂貴的查詢
某些類型的查詢由於它們的實現方式,通常會執行緩慢,這會影響集群的穩定性。這些查詢可以分類如下:

match查詢

match查詢是執行全文搜索的標準查詢,包括模糊匹配選項。

# 全文搜索的標準查詢,包括模糊匹配
GET /test_dawn/_search
{
 "query": {
     "match": {
        "title": "少年"
       }
 } 
}

term查詢

您可以使用term查詢根據價格、產品 ID 或用戶名等精確值查找文檔。
避免使用欄位term查詢。text
默認情況下,Elasticsearch 會在分析text過程中更改欄位的值。這會使查找欄位值的精確匹配變得困難。text
要搜索text欄位值,請改用match查詢。

# 精確查詢
GET /test_dawn/_search
{
  "query": {
    "term": {
      "_id": "vxvNeIIB7oKD63DUcC9h"
    }
  }
}

複合查詢

複合查詢包裝其他複合查詢或葉查詢,以組合它們的結果和分數,改變它們的行為,或者從查詢切換到過濾上下文。

用於組合多個葉或複合查詢子句的默認查詢,如 must或子句。and子句將 它們的分數組合在一起——匹配的子句越多越好——而and子句在過濾上下文中執行。 should must_not filter mustshould must_notfilter

返回匹配positive查詢的文檔,但減少也匹配negative查詢的文檔的分數。

包裝另一個查詢,但在過濾器上下文中執行它的查詢。所有匹配的文檔都被賦予相同的「常量」 _score

接受多個查詢並返回與任何查詢子句匹配的任何文檔的查詢。雖然bool查詢結合了所有匹配查詢的分數,但dis_max查詢使用單個最佳匹配查詢子句的分數。

使用函數修改主查詢返回的分數,以考慮流行度、新近度、距離或使用腳本實現的自定義演算法等因素。

bool查詢

匹配與其他查詢的布爾組合匹配的文檔的查詢。bool 查詢映射到 Lucene BooleanQuery。它是使用一個或多個布爾子句構建的,每個子句都有一個類型的出現。出現類型有:

名稱 描述
must 子句(查詢)必須出現在匹配的文檔中,並將有助於得分。
filter 子句(查詢)必須出現在匹配的文檔中。然而,與 must查詢的分數不同,將被忽略。過濾器子句在過濾器上下文中執行,這意味著忽略評分並考慮快取子句。
should 子句(查詢)應該出現在匹配的文檔中。
must_not 子句(查詢)不得出現在匹配的文檔中。子句在過濾器上下文中執行,這意味著忽略評分並考慮快取子句。因為忽略了評分,0所以返回所有文檔的評分。

該bool查詢採用更多匹配更好的方法,因此每個匹配must或should子句的分數將加在一起以提供_score每個文檔的最終結果。

# 符合查詢,其實我們只要記住:must(必須 )、must_not(必須不)、should(應該)的方式進行組合就可以了
GET /test_dawn/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "_id": "vxvNeIIB7oKD63DUcC9h"
          }
        }
      ],
      "should": [
        {
          "match": {
            "title": "少年說"
          }
        }
      ]
    }
  }
}

總結

  • 本次我主要列舉了,我再項目開發中比較常見的命令,當然這個只是官方文檔中的一些部分知識點,內容有很多可以先不必全部死記理解命令的使用場景即可。
  • 之前使用ELK收集日誌資訊,我都是使用的Kibana的可視化介面查詢的,但是在實際開發中習慣命令行查詢會靈活很多。
  • 本篇主要介紹的是原生命令行操作ElasticSearch,下一篇我們就要使用程式碼操作Elasticsearch Clients地址