Elasticsearch 技術分析(一): 基礎入門


簡介

Elasticsearch是一個高度可擴展的、開源的、基於 Lucene 的全文搜索和分析引擎。它允許您快速,近實時地存儲,搜索和分析大量數據,並支持多租戶。

Elasticsearch也使用Java開發並使用 Lucene 作為其核心來實現所有索引和搜索的功能,但是它的目的是通過簡單的 RESTful API 來隱藏 Lucene 的復雜性,從而讓全文搜索變得簡單。

不過,Elasticsearch 不僅僅是 Lucene 和全文搜索,我們還能這樣去描述它:

  • 分布式的實時文件存儲,每個字段都被索引並可被搜索
  • 分布式的實時分析搜索引擎
  • 可以擴展到上百台服務器,處理PB級結構化或非結構化數據

而且,所有的這些功能被集成到一個服務里面,你的應用可以通過簡單的RESTful API、各種語言的客戶端甚至命令行與之交互。

版本選擇

在決定使用 Elasticsearch 的時候首先要考慮的是版本問題,Elasticsearch 目前有三個常用的穩定的主版本:2.x,5.x,6.x(排除 0.x 和 1.x)。

Elasticsearch 可以在這里查看所有歷史版本,博主寫這篇博文的時候最新的是 Elasticsearch 6.4.2。你可能會發現沒有 3.x 和 4.x,ES 從 2.4.6 直接跳到了 5.0.0。這是為什么?

其實是為了ELK(ElasticSearch, logstash, kibana)技術棧的版本統一,免的給用戶帶來混亂。

我們知道 elasticsearch,kibana,logstash 都是 Elastic Stack 成員, 而且很多時候都是配合使用,那么為了協同開發,避免造成版本困惑,所以需要統一版本,至少保持在一個主版本號下。

在 Elasticsearch 是 2.x (2.x 的最后一版 2.4.6 的發布時間是 July 25, 2017) 的情況下,kibana 已經是 4.x(Kibana 4.6.5 的發布時間是 July 25, 2017),那么在 kibana 的下一主版本肯定是 5.x 了,所以 Elasticsearch 直接將自己的主版本發布為 5.0.0 了。統一之后,我們選版本就不會猶豫困惑了,我們選定 elasticsearch 的版本后再選擇相同版本的 kibana 就行了,不用擔憂版本不兼容的問題。

版本選擇可以從以下幾個方面考慮:

  • 版本問題
    2.x 版本較老,無法體驗新功能,且性能不如 5.x。
    6.x 版本有點新,網上資料相對比較少(開發時間充足的可以研究)。
  • 數據遷移
    2.x 版本數據可以直接遷移到 5.x;
    5.X 版本的數據可以直接遷移到 6.x; 但是 2.x 版本數據無法直接遷移到 6.x。
  • 周邊工具
    2.x 版本周邊工具版本比較混亂;Kibana 等工具的對應版本需要自己查,不好匹配。
    5.x 之后 Kibana 等工具的主版本號進行了統一。
  • Sql 語法支持
    2.x,5.x,6.x 都可以安裝 Elasticsearch-sql 插件,使用熟悉的SQL語法查詢 Elasticsearch。
    6.3.0 以后內置支持 SQL 模塊,這個 SQL 模塊是屬於 X-Pack 的一部分。

通過以上的版本號了解之后,綜合考慮,我起始選擇了 elasticsearch 6.4.0版本,其實主要是因為它新,kibana 也選擇了 kibana 6.4.0。但是等本地開發完成准備部署的時候,運維通知切換到5.6.0,因為公司其他部門的是5.6.0,方便統一維護,還好 API 變化不大。

環境搭建

安裝 Elasticsearch

Elasticsearch5.0之后的版本至少需要Java 8。可通過如下命令檢查Java版本,然后根據需要進行相應的安裝/升級。

java -version
echo $ JAVA_HOME

你可以從 elastic.co/download 下載你需要的版本的Elasticsearch,解壓之后即可使用。

如果是集群形式的,可在 ...\elasticsearch-5.6.0\config\elasticsearch.yml中配置一些你的集群信息:

cluster.name: my-application   # 集群名稱
path.data: /path/to/data       # ES數據存儲路徑
path.logs: /path/to/logs       # ES日志存儲路徑
node.name: node-1              # 當前節點的名稱
network.host: 192.168.0.1      # 配置當前結點綁定的IP地址,可設置為0.0.0.0
http.port: 9200                # 設置對外服務的HTTP端口,默認為9200

運行 Elasticsearch

elasticsearch 准備好之后,在安裝目錄中執行以下命令可以啟動運行:

Linux

./bin/elasticsearch

Windows

D:\...\elasticsearch-6.4.0\bin\elasticsearch.bat

運行成功之后(啟動日志里面會有.. started標志),瀏覽器訪問http://localhost:9200/?pretty,你能看到類似以下返回信息(各版本稍微不同):

{
  "name" : "AGXQ3qy",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "mg9t4Yi2TRud1JNwRY0bPA",
  "version" : {
    "number" : "6.4.0",
    "build_flavor" : "default",
    "build_type" : "zip",
    "build_hash" : "595516e",
    "build_date" : "2018-08-17T23:18:47.308994Z",
    "build_snapshot" : false,
    "lucene_version" : "7.4.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

這說明你的 Elasticsearch 集群已經啟動成功並且正常運行,接下來我們可以開始使用了。

可視化 web 界面

由於 Elasticsearch 的交互方式是 Rest 形式的,這種不是很直觀方便,我們先安裝圖視化界面,方便我們操作。可選擇的目前主要有 elasticsearch-head 和 kibana。

elasticsearch-head

elasticsearch-head 是一個用於瀏覽和與 elasticsearch 集群交互的Web前端。elasticsearch-head 是 elasticsearch 集群管理、數據可視化、增刪查改、查詢語句可視化工具。elasticsearch head 是托管的,可以在 github 下載或 fork。

有兩種運行和安裝elasticsearch-head的方法:

作為ElasticSearch的插件運行(這是首選方法)

  1. elasticsearch/bin/elasticsearch-plugin -install mobz/elasticsearch-head。
  2. open http://localhost:9200/_plugin/head/。

注意
插件的安裝方法,5.0之前為 plugin -install …,而在 5.0 以后為 elasticsearch-plugin -install …

作為獨立的webapp運行

  1. git clone git://github.com/mobz/elasticsearch-head.git
  2. 在瀏覽器中打開 index.html。現代瀏覽器需要使用 es-head。
  3. 默認情況下,es-head 將嘗試連接到http:// localhost:9200 /的集群節點。
    在連接框中輸入不同的節點地址,如果需要,單擊“連接”。

成功后的界面如下,可以看到集群的狀態信息:

由於 Head 安裝起來比較麻煩( 需要安裝 node.js ),網上資料也很多,所以我就不詳細說了,更多信息可參考:elasticsearch-head

kibana

Kibana 和 elasticsearch 同屬於 elastic 公司。 Kibana是一個開源分析和可視化平台,旨在與Elasticsearch協同工作。您使用Kibana搜索,查看和與存儲在 Elasticsearch 索引中的數據進行交互。您可以輕松地執行高級數據分析,並在各種圖表,表格和地圖中可視化您的數據。

Kibana 使您可以輕松理解大量數據。其簡單的基於瀏覽器的界面使您能夠快速創建和共享動態儀表板,實時顯示 Elasticsearch 查詢的更改。

設置 Kibana 非常容易。您可以安裝 Kibana 並在幾分鍾內開始探索您的 Elasticsearch 索引 - 無需代碼,無需額外的基礎架構。

同樣可在 kibana 選擇需要的對應版本(與 elasticsearch 版本對應),然后下載解壓即可使用,具體步驟如下:

  • 下載並解壓縮 Kibana。
  • 在編輯器中打開 config / kibana.yml。
  • 設置 elasticsearch.url 為您的Elasticsearch實例,如本地:elasticsearch.url: "http://localhost:9200"
  • 運行 bin/kibana(或bin\kibana.bat在Windows上)。
  • 瀏覽器輸入 http:// localhost:5601。

如果運行成功,但是無法訪問,可以關閉防火牆再試試。

基本概念

一切准備就緒,我們正式操作之前,先來了解一些 ES 的核心基本概念,從一開始就理解這些概念將極大地幫助簡化學習過程。

Elasticsearch是一個近乎實時(NRT)的搜索平台。這意味着從索引文檔到可搜索文檔的時間有一點延遲(通常是一秒)。通常有集群,節點,分片,副本等概念。

集群(Cluster)

集群(cluster)是一組具有相同cluster.name的節點集合,他們協同工作,共享數據並提供故障轉移和擴展功能,當然一個節點也可以組成一個集群。

集群由唯一名稱標識,默認情況下為“elasticsearch”。此名稱很重要,因為如果節點設置為按名稱加入集群的話,則該節點只能是集群的一部分。

確保不同的環境中使用不同的集群名稱,否則最終會導致節點加入錯誤的集群。

【集群健康狀態】

集群狀態通過 來標識

  • 綠色 - 一切都很好(集群功能齊全)。
  • 黃色 - 所有數據均可用,但尚未分配一些副本(集群功能齊全)。
  • 紅色 - 某些數據由於某種原因不可用(集群部分功能)。

注意:當群集為紅色時,它將繼續提供來自可用分片的搜索請求,但您可能需要盡快修復它,因為存在未分配的分片。

要檢查群集運行狀況,我們可以在 Kibana 控制台中運行以下命令GET /_cluster/health,得到如下信息:

{
  "cluster_name": "elasticsearch",
  "status": "yellow",
  "timed_out": false,
  "number_of_nodes": 1,
  "number_of_data_nodes": 1,
  "active_primary_shards": 28,
  "active_shards": 28,
  "relocating_shards": 0,
  "initializing_shards": 0,
  "unassigned_shards": 5,
  "delayed_unassigned_shards": 0,
  "number_of_pending_tasks": 0,
  "number_of_in_flight_fetch": 0,
  "task_max_waiting_in_queue_millis": 0,
  "active_shards_percent_as_number": 84.84848484848484
}

節點(Node)

節點,一個運行的 ES 實例就是一個節點,節點存儲數據並參與集群的索引和搜索功能。

就像集群一樣,節點由名稱標識,默認情況下,該名稱是在啟動時分配給節點的隨機通用唯一標識符(UUID)。如果不需要默認值,可以定義所需的任何節點名稱。此名稱對於管理目的非常重要,您可以在其中識別網絡中哪些服務器與 Elasticsearch 集群中的哪些節點相對應。

可以將節點配置為按集群名稱加入特定集群。默認情況下,每個節點都設置為加入一個名為 cluster 的 elasticsearch 集群,這意味着如果您在網絡上啟動了許多節點並且假設它們可以相互發現 - 它們將自動形成並加入一個名為 elasticsearch 的集群。

索引(Index)

索引是具有某些類似特征的文檔集合。例如,您可以擁有店鋪數據的索引,商品的一個索引以及訂單數據的一個索引。

索引由名稱標識(必須全部小寫),此名稱用於在對其中的文檔執行索引,搜索,更新和刪除操作時引用索引。

類型(Type)

類型,曾經是索引的邏輯類別/分區,允許您在同一索引中存儲不同類型的文檔,例如,一種類型用於用戶,另一種類型用於博客帖子。

在 6.0.0 中棄用,以后將不再可能在索引中創建多個類型,並且將在更高版本中刪除類型的整個概念

文檔(Document)

文檔是可以建立索引的基本信息單元。例如,您可以為單個客戶提供文檔,為單個產品提供一個文檔,為單個訂單提供一個文檔。該文檔以JSON(JavaScript Object Notation)表示,JSON是一種普遍存在的互聯網數據交換格式。

在索引/類型中,您可以根據需要存儲任意數量的文檔。請注意,盡管文檔實際上駐留在索引中,但實際上必須將文檔編入索引/分配給索引中的類型。

分片(Shards)

索引可能存儲大量可能超過單個節點的硬件限制的數據。例如,占用1TB磁盤空間的十億個文檔的單個索引可能不適合單個節點的磁盤,或者可能太慢而無法單獨從單個節點提供搜索請求。

為了解決這個問題,Elasticsearch 提供了將索引細分為多個稱為分片的功能。創建索引時,只需定義所需的分片數即可。每個分片本身都是一個功能齊全且獨立的“索引”,可以托管在集群中的任何節點上。

設置分片的目的及原因主要是:

  • 它允許您水平拆分/縮放內容量
  • 它允許您跨分片(可能在多個節點上)分布和並行化操作,從而提高性能/吞吐量

分片的分布方式以及如何將其文檔聚合回搜索請求的機制完全由 Elasticsearch 管理,對用戶而言是透明的。

在可能隨時發生故障的網絡/雲環境中,分片非常有用,建議使用故障轉移機制,以防分片/節點以某種方式脫機或因任何原因消失。為此,Elasticsearch 允許您將索引的分片的一個或多個副本制作成所謂的副本分片或簡稱副本。

副本(Replicasedit)

副本,是對分片的復制。目的是為了當分片/節點發生故障時提供高可用性,它允許您擴展搜索量/吞吐量,因為可以在所有副本上並行執行搜索。

總而言之,每個索引可以拆分為多個分片。索引也可以復制為零次(表示沒有副本)或更多次。復制之后,每個索引將具有主分片(從原始分片復制而來的)和復制分片(主分片的副本)。

可以在創建索引時為每個索引定義分片和副本的數量。創建索引后,您也可以隨時動態更改副本數。您可以使用_shrink_splitAPI 更改現有索引的分片數,但這不是一項輕松的任務,所以預先計划正確數量的分片是最佳方法。

默認情況下,Elasticsearch 中的每個索引都分配了5個主分片和1個副本,這意味着如果集群中至少有兩個節點,則索引將包含5個主分片和另外5個副本分片(1個完整副本),總計為每個索引10個分片。

小結

我們假設有一個集群由三個節點組成(Node1 , Node2 , Node3)。 它有兩個主分片(P0 , P1),每個主分片有兩個副本分片(R0 , R1)。相同分片的副本不會放在同一節點,所以我們的集群看起來如下圖所示 “有三個節點和一個索引的集群”。

類似於關系型數據庫:數據庫集群,假如有個用戶表,我擔心數據量過大,我新建了多個用戶表(即 Shard),將用戶信息數據切分成多份,然后根據某種規則分到這些用戶表中,我又擔心某個表會出現異常造成數據丟失,我又將每個表分別備份了一次(即 Replica )。

副本是乘法,越多越浪費,但也越保險。分片是除法,分片越多,單分片數據就越少也越分散。

另外,我們可以畫一個對比圖來類比傳統關系型數據庫:

  • 關系型數據庫 -> Databases(庫) -> Tables(表) -> Rows(行) -> Columns(列)。
  • Elasticsearch -> Indeces(索引) -> Types(類型) -> Documents(文檔) -> Fields(屬性)。

Elasticsearch集群可以包含多個索引(indices)(數據庫),每一個索引可以包含多個類型 (Types)(表),每一個類型包含多個文檔(documents)(行),然后每個文檔包含多個字段(Fields)(列)。

雖然這么類比,但是畢竟是兩個差異化的產品,而且上面也說過在以后的版本中類型 (Types) 可能會被刪除,所以一般我們創建索引都是一個種類對應一個索引。生鮮就創建商品的索引,生活用品就創建生活用品的索引,而不會說創建一個商品的索引,里面既包含生鮮的類型,又包含生活用品的類型。

而且你可能已經注意到索引(index)這個詞在Elasticsearch中有着不同的含義,所以有必要在此做一下區分:

「索引」含義的區分

  • 索引(名詞) 如上文所述,一個索引(index)就像是傳統關系數據庫中的數據庫,它是相關文檔存儲的地方,index的復數是 indices 或 indexes。
  • 索引(動詞) 「索引一個文檔」表示把一個文檔存儲到索引(名詞)里,以便它可以被檢索或者查詢。這很像SQL中的INSERT關鍵字,差別是,如果文檔已經存在,新的文檔將覆蓋舊的文檔。
  • 倒排索引 傳統數據庫為特定列增加一個索引,例如B-Tree索引來加速檢索。Elasticsearch和Lucene使用一種叫做倒排索引(inverted index)的數據結構來達到相同目的。

與Elasticsearch交互

目前與 elasticsearch 交互主要有兩種方式:Client API 和 RESTful API。

Client API方式

Elasticsearch 為以下語言提供了官方客戶端 --Groovy、JavaScript、.NET、 PHP、 Perl、 Python 和 Ruby--還有很多社區提供的客戶端和插件,所有這些都可以在 Elasticsearch Clients 中找到。后面再開一篇來詳細說明。

RESTful API with JSON over HTTP

所有其他語言可以使用 RESTful API 通過端口 9200 和 Elasticsearch 進行通信,你可以用你最喜愛的 web 客戶端訪問 Elasticsearch 。事實上,正如你所看到的,你甚至可以使用 curl 命令來和 Elasticsearch 交互。

一個 Elasticsearch 請求和任何 HTTP 請求一樣由若干相同的部件組成:

curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'

< >標記的部件:

數據格式

在應用程序中對象很少只是一個簡單的鍵和值的列表。通常,它們擁有更復雜的數據結構,可能包括日期、地理信息、其他對象或者數組等。

也許有一天你想把這些對象存儲在數據庫中。使用關系型數據庫的行和列存儲,這相當於是把一個表現力豐富的對象擠壓到一個非常大的電子表格中:你必須將這個對象扁平化來適應表結構,通常一個字段對應一列,而且又不得不在每次查詢時重新構造對象。

Elasticsearch 是面向文檔的,意味着它存儲整個對象或文檔。Elasticsearch 不僅存儲文檔,而且 每個文檔的內容可以被檢索。在 Elasticsearch 中,你對文檔進行索引、檢索、排序和過濾而不是對行列數據。這是一種完全不同的思考數據的方式,也是 Elasticsearch 能支持復雜全文檢索的原因。

Elasticsearch 使用 JavaScript Object Notation 或者 JSON 作為文檔的序列化格式。JSON 序列化被大多數編程語言所支持,並且已經成為 NoSQL 領域的標准格式。 它簡單、簡潔、易於閱讀。幾乎所有的語言都有相應的模塊可以將任意的數據結構或對象 轉化成 JSON 格式,只是細節各不相同。

{
  "_index" :   "megacorp",
  "_type" :    "employee",
  "_id" :      "1",
  "_version" : 1,
  "found" :    true,
  "_source" :  {
      "first_name" :  "John",
      "last_name" :   "Smith",
      "age" :         25,
      "about" :       "I love to go rock climbing",
      "interests":  [ "sports", "music" ]
  }
}

索引的應用

一切准備就緒之后我們開始來使用起來,體驗 ElasticSearch 的世界。首先,我們來查看我們的所有索引信息:

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

得到如下結果信息:

{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": ".kibana",
        "_type": "config",
        "_id": "5.6.0",
        "_score": 1,
        "_source": {
          "buildNum": 15523
        }
      }
    ]
  }
}

可以發現,當前只有一個索引,是.kibana,當然這不是我們自己的,這是kibana的。

創建第一個簡單索引

NBA的新的賽季又開始了,我相信大部分人有精彩比賽的時候還是會去關注的,我們創建一個 NBA 球隊的索引,開始我們的學習之路,索引名稱需是小寫。

PUT nba
{
  "settings":{
    "number_of_shards": 3,   
    "number_of_replicas": 1	
  },
  "mappings":{
    "nba":{
      "properties":{
        "name_cn":{ 
          "type":"text"
        },
        "name_en":{
          "type":"text"
        },
        "gymnasium":{
          "type":"text"
        },
        "topStar":{
          "type":"text"
        },
        "championship":{
          "type":"integer"
        },
        "date":{
          "type":"date",
          "format":"yyyy-MM-dd HH:mm:ss|| yyy-MM-dd||epoch_millis"
        }
      }
    }
  }
}

字段說明:

字段名稱 字段說明
nba 索引
number_of_shards 分片數
number_of_replicas 副本數
name_cn 球隊中文名
name_en 球隊英文名
gymnasium 球館名稱
championship 總冠軍次數
topStar 當家球星
date 加入NBA年份

如果格式書寫正確,我們會得到如下返回信息,表示創建成功

{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "nba"
}

新增索引數據

索引創建完成之后,我們往索引中加入球隊數據,1,2,3 是我們指定的 ID,如果不寫 ES 會默認ID。

其實我們可以不創建上面的索引 mapping 直接推送數據,但是這樣 ES 會根據數據信息自動為我們設定字段類型,這會造成索引信息不准確的風險。

PUT /nba/nba/1
{
  "name_en":"San Antonio Spurs SAS",
  "name_cn":"聖安東尼安馬刺",
  "gymnasium":"AT&T中心球館",
  "championship": 5,
  "topStar":"蒂姆·鄧肯",
  "date":"1995-04-12"
}

PUT /nba/nba/2
{
  "name_en":"Los Angeles Lakers",
  "name_cn":"洛杉磯湖人",
  "gymnasium":"斯台普斯中心球館",
  "championship": 16,
  "topStar":"科比·布萊恩特",
  "date":"1947-05-12"
}

PUT /nba/nba/3
{
  "name_en":"Golden State Warriors",
  "name_cn":"金州勇士隊",
  "gymnasium":"甲骨文球館",
  "championship": 6,
  "topStar":"斯蒂芬·庫里",
  "date":"1949-06-13"
}

PUT /nba/nba/4
{
  "name_en":"Miami Heat",
  "name_cn":"邁阿密熱火隊",
  "gymnasium":"美國航空球場",
  "championship": 3,
  "topStar":"勒布朗·詹姆斯",
  "date":"1988-06-13"
}

PUT /nba/nba/5
{
  "name_en":"Cleveland Cavaliers",
  "name_cn":"克利夫蘭騎士隊",
  "gymnasium":"速貸球館",
  "championship": 1,
  "topStar":"勒布朗·詹姆斯",
  "date":"1970-06-13"
}

索引數據 PUT 成功,會返回如下信息

{
  "_index": "nba",
  "_type": "nba",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": true
}

查詢索引數據

上面新增完數據之后,這時候我們再執行開始的 MATCH_ALL ,就會發現我們自己的索引信息也在查詢的結果里面了,只是查詢的結果是全部信息,其中包括索引、分片和副本的信息,內容比較多。我們可單獨查詢自己需要的索引信息。

Elasticsearch 提供豐富且靈活的查詢語言叫做 **DSL 查詢 (Query DSL) **,它允許你構建更加復雜、強大的搜索。

1.匹配查詢 match,match_all

我們嘗試一個最簡單的搜索全部員工的請求:

# 查詢全部球隊的信息

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

得到的查詢結果如下

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 3,
    "successful": 3,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 1,
    "hits": [
      {
        "_index": "nba",
        "_type": "nba",
        "_id": "2",
        "_score": 1,
        "_source": {
          "name_en": "Los Angeles Lakers",
          "name_cn": "洛杉磯湖人",
          "gymnasium": "斯台普斯中心球館",
          "championship": 16,
          "topStar": "科比·布萊恩特",
          "date": "1947-05-12"
        }
      },
      {
        "_index": "nba",
        "_type": "nba",
        "_id": "1",
        "_score": 1,
        "_source": {
          "name_en": "San Antonio Spurs SAS",
          "name_cn": "聖安東尼安馬刺",
          "gymnasium": "AT&T中心球館",
          "championship": 5,
          "topStar": "蒂姆·鄧肯",
          "date": "1995-04-12"
        }
      },
      {
        "_index": "nba",
        "_type": "nba",
        "_id": "3",
        "_score": 1,
        "_source": {
          "name_en": "Golden State Warriors",
          "name_cn": "金州勇士隊",
          "gymnasium": "甲骨文球館",
          "championship": 6,
          "topStar": "斯蒂芬·庫里",
          "date": "1949-06-13"
        }
        ···
      }
    ]
  }
}

響應的數據結果分為兩部分

{
----------------first part--------------------
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 3,
    "successful": 3,
    "skipped": 0,
    "failed": 0
  },
---------------second part---------------------
  "hits": {
    "total": 0,
    "max_score": null,
    "hits": []
  }
}

第一部分為:分片副本信息,第二部分 hits 包裝的為查詢的數據集。

注意:
響應內容不僅會告訴我們哪些文檔被匹配到,而且這些文檔內容完整的被包含在其中—我們在給用戶展示搜 索結果時需要用到的所有信息都有了。

# 查詢英文名稱為:"Golden State Warriors" 的球隊信息

GET /nba/nba/_search
{
   "query": {
        "match": {
            "name_en": "Golden State Warriors"
        }
    }
}

可得到的查詢結果為:

{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 3,
    "successful": 3,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1.9646256,
    "hits": [
      {
        "_index": "nba",
        "_type": "nba",
        "_id": "3",
        "_score": 1.9646256,
        "_source": {
          "name_en": "Golden State Warriors",
          "name_cn": "金州勇士隊",
          "gymnasium": "甲骨文球館",
          "championship": 6,
          "topStar": "斯蒂芬·庫里",
          "date": "1949-06-13"
        }
      }
    ]
  }
}

2.過濾查詢 Filter

我們讓搜索變的復雜一些。我們想要找到當家球星是勒布朗·詹姆斯,但是我們只想得到總冠軍多余1次的球隊。我們的語句將做一些改變用來添加過濾器(filter),它允許我們有效的執行一個結構化搜索:

GET /nba/nba/_search
{
  "query": {
    "bool": {
      "filter": {
        "range": {
          "championship": {
            "gt": 1
          }
        }
      },
      "must": {
        "match": {
          "topStar": "勒布朗·詹姆斯"
        }
      }
    }
  }
}

我們發現每次查詢,查詢結果里面都有一個 _score字段,一般Elasticsearch根據相關評分排序,相關評分是根據文檔與語句的匹配度來得出, _score值越高說明匹配度越高。

Elasticsearch如何進行全文字段搜索且首先返回相關性性最大的結果。相關性(relevance)概念在Elasticsearch中非常重要,而這也是它與傳統關系型數據庫中記錄只有匹配和不匹配概念最大的不同。

結束語

由於篇幅限制,對於 ElasticSearch 最基本的概念暫時先介紹這么多,要寫的內容還很多,經過接近一個月的技術調研和開發,目前對於 ES 也有一個總體的技術了解,但是很多細節還是需要琢磨的,ES 的功能確實強大且豐富,要想熟練耍起來,還是需要一定時間的。

后面會繼續介紹 ES的相關內容,大概包括 ES 服務的 Java 語言搭建ES 的 SQL方式查詢等等內容。有興趣的可以先關注本人的博客,由於質量要求大概一星期更新一篇。

另外,我這里添加一個園友ReyCG對本篇文章的思維導圖總結,通過該思維導圖我們可以更加清晰的理解Elasticsearch的基礎信息。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM