Elasticsearch 技術分析: 基礎入門

簡介

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

Elasticsearch也使用Java開發並使用 Lucene 做爲其核心來實現全部索引和搜索的功能,可是它的目的是經過簡單的 RESTful API 來隱藏 Lucene 的複雜性,從而讓全文搜索變得簡單。前端

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

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

並且,全部的這些功能被集成到一個服務裏面,你的應用能夠經過簡單的RESTful API、各類語言的客戶端甚至命令行與之交互。node

版本選擇

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

Elasticsearch 能夠在這裏查看全部歷史版本,博主寫這篇博文的時候最新的是 Elasticsearch 6.4.2。你可能會發現沒有 3.x 和 4.x,ES 從 2.4.6 直接跳到了 5.0.0。這是爲何?github

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

咱們知道 elasticsearch,kibana,logstash 都是 Elastic Stack 成員, 並且不少時候都是配合使用,那麼爲了協同開發,避免形成版本困惑,因此須要統一版本,至少保持在一個主版本號下。sql

在 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的基礎信息。


我的公衆號:JaJian

歡迎長按下圖關注公衆號:JaJian!

按期爲你奉上分佈式,微服務等一線互聯網公司相關技術的講解和分析。


1557975294786730.png

相關文章
相關標籤/搜索