起源html
在沒有先後端分離概念以前,一個網站的完成老是「all in one」,在這個階段,頁面、數據、渲染所有在服務端完成,這樣作的最大的弊端是後期維護,擴展極其痛苦,開發人員必須同時具有先後端知識。因而後來慢慢的興起了先後端分離的思想:即後端負責數據編造,而前端則負責數據渲染,前端靜態頁面調用指定 api 獲取到有固定格式的數據,再將數據展現出來,這樣呈現給用戶的就是一個」動態「的過程。前端
而關於 api 這部分的設計則成了一個問題。如何設計出一個便於理解,容易使用的 api 則成了一個問題,而所謂的 RESTful 就是用來規範咱們的 API 的一種約束。java
做爲 REST,實際上是 Representational State Transfer(表象層狀態轉變)三個單詞的縮寫,它由 Roy Fielding(Fielding 是 HTTP 協議(1.0 版和 1.1 版)的主要設計者、Apache 服務器軟件的做者之1、Apache 基金會的第一任主席)於2000 年論文中提出,他在論文中提到:"我這篇文章的寫做目的,就是想在符合架構原理的前提下,理解和評估以網絡爲基礎的應用軟件的架構設計,獲得一個功能強、性能好、適宜通訊的架構。REST 指的是一組架構約束條件和原則。"若是一個架構符合 REST 的約束條件和原則,咱們就稱它爲 RESTful 架構。node
要理解 RESTful 架構,最好的方法就是去理解 Representational StateTransfer 這個詞組究竟是什麼意思,它的每個詞表明瞭什麼涵義。若是你把這個名稱搞懂了,也就不難體會 REST 是一種什麼樣的設計。linux
資源(Resources)git
REST 的名稱"表現層狀態轉化"中,省略了主語。"表現層"其實指的是"資源"(Resources)的"表現層"。github
所謂"資源",就是網絡上的一個實體,或者說是網絡上的一個具體信息。它能夠是一段文本、一張圖片、一首歌曲、一種服務,總之就是一個具體的實在。算法
要讓一個資源能夠被識別,須要有個惟一標識,在 Web 中這個惟一標識就是URI(Uniform Resource Identifier)。數據庫
URI 既能夠當作是資源的地址,也能夠當作是資源的名稱。若是某些信息沒有使用 URI 來表示,那它就不能算是一個資源,只能算是資源的一些信息而已。編程
你能夠用一個 URI(統一資源定位符)指向它,每種資源對應一個特定的 URI。
要獲取這個資源,訪問它的 URI 就能夠,所以 URI 就成了每個資源的地址或獨一無二的識別符。
所謂"上網",就是與互聯網上一系列的"資源"互動,調用它的 URI。
URI 設計技巧
一、使用 _ 或 - 來讓 URI 可讀性更好
曾經 Web 上的 URI 都是冰冷的數字或者無心義的字符串,但如今愈來愈多的網站使用_或-來分隔一些單詞,讓 URI 看上去更爲人性化。例如國內比較出名的開源中國社區,它上面的新聞地址就採用這種風格,如
二、使用 / 來表示資源的層級關係
例如上述/git/git/commit/e3af72cdafab5993d18fae056f87e1d675913d08就表示了一個多級的資源,指的是 git 用戶的 git 項目的某次提交記錄,又例如/orders/2012/10 能夠用來表示 2012 年 10 月的訂單記錄。
三、使用 ? 用來過濾資源
不少人只是把?簡單的當作是參數的傳遞,很容易形成 URI 過於複雜、難以理解。能夠把?用於對資源的過濾,例如/git/git/pulls 用來表示 git 項目的全部推入請求,而/pulls?state=closed 用來表示 git 項目中已經關閉的推入請求,這種 URL 一般對應的是一些特定條件的查詢結果或算法運算結果。
, 或; 能夠用來表示同級資源的關係
有時候咱們須要表示同級資源的關係時,能夠使用,或;來進行分割。例如哪天github 能夠比較某個文件在隨意兩次提交記錄之間的差別,或許能夠使用/git/git
/block-sha1/sha1.h/compare/e3af72cdafab5993d18fae056f87e1d675913d08;bd63e61bdf38e872d5215c07b264dcc16e4febca 做爲 URI。不過,如今 github 是使用…來作這個事情的,例如/git/git/compare/master…next。
四、URI 不該該包含動詞
由於"資源"表示一種實體,因此應該是名詞,URI 不該該有動詞,動詞應該放在 HTTP 協議中。
舉例來講,某個 URI 是/posts/show/1,其中 show 是動詞,這個 URI 就設計錯了,正確的寫法應該是/posts/1,而後用 GET 方法表示 show。
若是某些動做是 HTTP 動詞表示不了的,你就應該把動做作成一種資源。好比網上匯款,從帳戶 1向帳戶 2匯款 500 元,錯誤的 URI 是:
POST /accounts/1/transfer/500/to/2
正確的寫法是把動詞 transfer 改爲名詞 transaction,資源不能是動詞,可是能夠是一種服務。
五、URI 中不宜加入版本號
例如:
http://www.example.com/app/1.0/foo
http://www.example.com/app/1.1/foo
http://www.example.com/app/2.0/foo
由於不一樣的版本,能夠理解成同一種資源的不一樣表現形式,因此應該採用同一個 URI。版本號能夠在 HTTP 請求頭信息的 Accept 字段中進行區分。
表現層(Representation)
"資源"是一種信息實體,它能夠有多種外在表現形式。咱們把"資源"具體呈現出來的形式,叫作它的"表現層"(Representation)。
好比,文本能夠用 txt 格式表現,也能夠用 HTML 格式、XML 格式、JSON 格式表現,甚至能夠採用二進制格式;圖片能夠用 JPG 格式表現,也能夠用 PNG格式表現。
URI 只表明資源的實體,不表明它的形式。嚴格地說,有些網址最後的".html"後綴名是沒必要要的,由於這個後綴名錶示格式,屬於"表現層"範疇,而URI 應該只表明"資源"的位置。它的具體表現形式,應該在 HTTP 請求的頭信息中用 Accept 和 Content-Type 字段指定,這兩個字段纔是對"表現層"的描述。
狀態轉化(State Transfer)
訪問一個網站,就表明了客戶端和服務器的一個互動過程。在這個過程當中,勢必涉及到數據和狀態的變化。
互聯網通訊協議 HTTP 協議,是一個無狀態協議。這意味着,全部的狀態都保存在服務器端。所以,若是客戶端想要操做服務器,必須經過某種手段,讓服務器端發生"狀態轉化"(State Transfer)。而這種轉化是創建在表現層之上的,因此就是"表現層狀態轉化"。
客戶端用到的手段,目前來講只能是 HTTP 協議。具體來講,就是 HTTP 協議裏面,四個表示操做方式的動詞:GET、POST、PUT、DELETE。它們分別對應四種基本操做:GET 用來獲取資源,POST 用來新建資源(也能夠用於更新資源),PUT用來更新資源,DELETE 用來刪除資源。GET、PUT 和 DELETE 請求都是冪等的,不管對資源操做多少次,結果老是同樣的, POST 不是冪等的。
什麼是 RESTful 架構
綜合上面的解釋,咱們總結一下什麼是 RESTful 架構:
1.架構裏,每個 URI 表明一種資源;
2.客戶端和服務器之間,傳遞這種資源的某種表現層;
3.客戶端經過四個 HTTP 動詞(get、post、put、delete),對服務器端資源進行操做,實現」表現層狀態轉化」。
注意:REST 架構風格並非綁定在 HTTP 上,只不過目前 HTTP 是惟一與 REST相關的實例。因此咱們這裏描述的 REST 也是經過 HTTP 實現的 REST。
辨析 URI、URL、URN
RFC 3986 中是這樣說的:
A Uniform Resource Identifier (URI) 是一個緊湊的字符串用來標示抽象或物理資源。一個 URI 能夠進一步被分爲定位符、名字或二者都是. 術語「Uniform Resource Locator」(URL) 是 URI 的子集, 除了肯定一個資源,還提供一種定位該資源的主要訪問機制。
因此,URI = Universal Resource Identifier 統一資源標誌符,包含 URL和URN,支持的協議有 http、https、ftp、mailto、magnet、telnet、data、file、nfs、gopher、ldap 等,java 還大量使用了一些非標準的定製模式,如 rmi,jar、jndi 和 doc,來實現各類不一樣用途。
URL = Universal Resource Locator 統一資源定位符,URL 惟一地標識一個資源在 Internet 上的位置。無論用什麼方法表示,只要能定位一個資源,就叫URL。
URN = Universal Resource Name 統一資源名稱,URN 它命名資源但不指定如何定位資源,好比:只告訴你一我的的姓名,不告訴你這我的在哪。
對於一個資源來講,URN 就比如他的名字,而 URL 就比如是資源的街道住址。
換句話說,URN 標識了一個資源項目,而 URL 則提供了一種找到他的方法。
好比同時指定基本的獲取機制和網絡位置。舉個例子,
http://example.org/wiki/Main_Page,指向了一個被識別爲/wike/Main_Page的資源,這個資源的表現形式是 HTML 和相關的代碼。而獲取這個資源的方法是在網絡中從一個名爲 example.org 的主機上,經過 HTTP( Hypertext TransferProtocol)得到。
而 URN 則是一種在特定的名稱空間中經過經過名字來標識資源的 URI。當討論一種資源而不須要知道它的位置或者如何去得到它的時候,就能夠使用 URN。
例如,在 International Standard Book Number (ISBN)系統中,* ISBN
0-486-27557-4 用來指定莎士比亞的做品《羅密歐與朱麗葉》的一個特定版本。
指示這一版本的 URN 是 urn:isbn:0-486-27557-4*,可是若是想要得到這個版本的書,就須要知道它的位置,這樣就必須知道它的 URL。
官網的說法:Elasticsearch 是一個開源的分佈式 RESTful 搜索和分析引擎,可以解決愈來愈多不一樣的應用場景。
看一個應用場景,常見的 WEB 應用日誌分析。通常咱們會怎麼作?
登陸到每臺服務器上,直接在日誌文件中 grep、awk 就能夠得到本身想要的信息。但在規模較大的場景中,此方法效率低下,面臨問題包括日誌量太大如何歸檔、文本搜索太慢怎麼辦、如何多維度查詢。
這個時候咱們但願集中化的日誌管理,全部服務器上的日誌收集彙總。常看法決思路是創建集中式日誌收集系統,將全部節點上的日誌統一收集,管理,訪問。
這樣對於大型系統來講,都是一個分佈式部署的架構,不一樣的服務模塊部署在不一樣的服務器上,問題出現時,大部分狀況須要根據問題暴露的關鍵信息,定位到具體的服務器和服務模塊,構建一套集中式日誌系統,能夠提升定位問題的效率。
一個完整的集中式日誌系統,須要包含如下幾個主要特色:
收集-可以採集多種來源的日誌數據
傳輸-可以穩定的把日誌數據傳輸到中央系統
存儲-如何存儲日誌數據分析-能夠支持
UI 分析警告-可以提供錯誤報告,監控機制
ELK就是這樣一整套解決方案,而且都是開源軟件,之間互相配合使用,完美銜接,高效的知足了不少場合的應用,而不只僅是日誌分析。
ELK是三個開源軟件的縮寫,分別表示:Elasticsearch , Logstash, Kibana , 它們都是開源軟件。
Elasticsearch是個開源分佈式搜索引擎,提供蒐集、分析、存儲數據三大功能。它的特色有:分佈式,零配置,自動發現,索引自動分片,索引副本機制,restful風格接口,多數據源,自動搜索負載等。
Logstash 主要是用來日誌的蒐集、分析、過濾日誌的工具,支持大量的數據獲取方式。通常工做方式爲 c/s 架構,client端安裝在須要收集日誌的主機上,server端負責將收到的各節點日誌進行過濾、修改等操做在一併發往 elasticsearch上去。
Kibana 也是一個開源和免費的工具,Kibana 能夠爲 Logstash 和
ElasticSearch 提供的日誌分析友好的 Web 界面,能夠幫助彙總、分析和搜索重要數據日誌。
新增了一個 Beats 系列組件,它是一個輕量級的日誌收集處理工具(Agent),Beats 佔用資源少,適合於在各個服務器上搜集日誌或信息後傳輸給 Logstash。
加入 Beats 系列組件後,官方名稱就變爲了 Elastic Stack,產品以下:
環境和安裝
運行環境爲 Linux,演示服務器操做系統版本狀況以下:
由於 Elastic Stack中主要組件都是用 Java 寫的,因此操做系統上還應該安裝好 Java,本次以 Elasticsearch 7 版本爲主,因此,須要安裝 JDK1.8 以上。
而 Elastic Stack系列產品咱們能夠到 Elastic的官網上去下載:
https://www.elastic.co/cn/downloads
選擇 7.7.0版本爲本次版本,從具體的下載頁面能夠看到 Elastic Stack支持各類形式的安裝。
選擇以避免安裝的壓縮包的形式。下載後上傳到服務器解壓縮便可運行。
Elasticsearch 默認不容許用 root用戶運行,會報錯,並且從服務器安全的角度來講,也不該該以 root用戶來作平常工做,所以咱們新建一個用戶 elk並以elk用戶登陸。
Elasticsearch
用 tar -xvf命令解壓壓縮包elasticsearch-7.7.0-linux-x86_64.tar.gzip後進入elasticsearch-7.7.0文件夾中的 bin文件夾,並執行命令./elasticsearch。
待啓動完成.....
輸入 curl http://localhost:9200
顯示:
表示Elasticsearch運行成功了,咱們試着在本地瀏覽器進行訪問
卻顯示「拒絕了咱們的鏈接請求」,所以咱們還須要配置一下 Elasticsearch以容許咱們進行外網訪問,進入 elasticsearch-7.7.0下的 config目錄,編輯elasticsearch.yml文件,刪除 network.host前的#字符,並寫入服務器的地址並保存。
再次運行,可是此次卻出了錯
從錯誤提示咱們能夠知道,還需對 Elasticsearch配置作適當修改,從新編輯elasticsearch.yml文件,並作以下修改:
再次啓動,並在瀏覽器中訪問
顯示 Elasticsearch運行並訪問成功!
咱們知道,Elasticsearch提供的是 restful風格接口,咱們用瀏覽器訪問不是很方便,除非咱們自行編程訪問 restful接口。這個時候,就能夠用上 Kibana 了,它已經爲咱們提供了友好的 Web 界面,方便咱們後面對 Elasticsearch的學習。
接下來咱們安裝運行 Kibana。
一樣用 tar -xvf命令解壓壓縮包,進入解壓後的目錄。爲了方便咱們的訪問和鏈接 Elasticsearch,也須要進入 Kibana的 config 目錄對 Kibana 進行配置。
而後進入 Kibana的 bin 目錄運行./kibana,kibana由於是用 node.js 編寫的,因此啓動和運行較慢,須要等待一段時間:
從提示咱們能夠看出,kibana的訪問端口是 5601,咱們依然在本地瀏覽器中訪問:
等候幾分鐘之後,就會進入 kibana的主界面
咱們通常會用ps -ef來查詢某個應用是否在 Linux系統中啓動,好比Elasticsearch,
咱們用 ps -ef|grep java 或者 ps -ef|grep elasticsearch都可
可是當咱們嘗試 ps -ef|grep kibana,倒是不行的
由於 kibana 是 node 寫的,因此 kibana 運行的時候是運行在 node 裏面,咱們要查詢的話,只能 ps -ef|grep node
或者使用 netstat -tunlp|grep 5601
由於咱們的kibana開放的端口是5601,因此看到5601端口被 Listen (監聽),說明 kibana啓動成功。
附:netstat參數說明:
-t (tcp)僅顯示 tcp相關選項
-u (udp)僅顯示 udp相關選項
-n 拒絕顯示別名,能顯示數字的所有轉化成數字。
-l 僅列出有在 Listen (監聽) 的服務狀態
-p 顯示創建相關連接的程序名
更多 netstat的相關說明,自行查閱 Linux手冊
點擊面板中的「Dev Tools」按鈕,進入 Dev 工具,開始咱們的 Elasticsearch初次訪問之旅。
在左邊命令窗口中輸入 put enjoy_test,並點擊相關按鈕 ,因而看到右
邊的結果窗口中 es給咱們返回了處理結果,表示咱們在 es中建立索引成功。
要查看咱們剛剛建立的索引,執行「get enjoy_test」
往這個索引中添加文檔,執行:
PUT /enjoy_test/_doc/1
{
"msg":"Hello World!"
}
查詢咱們剛剛加入的文檔,執行「get /enjoy_test/_doc/1」
從上面的例子中,咱們看到了不少熟悉又陌生的概念,好比索引、文檔等等。這些概念和咱們平時看到的數據庫裏的好比索引有什麼區別呢?
舉個例子,如今咱們要保存唐宋詩詞,數據庫中咱們們會怎麼設計?詩詞表咱們可能的設計以下:
朝代 |
做者 |
詩詞年代 |
標題 |
詩詞全文 |
唐 |
李白 |
|
靜夜思 |
牀前明月光,疑是地上霜。舉頭望明月,低頭思故鄉。 |
宋 |
李清照 |
|
如夢令 |
常記溪亭日暮,沉醉不知歸路,興盡晚回舟,誤入藕花深處。爭渡,爭渡,驚起一灘鷗鷺。 |
…. |
…. |
… |
…. |
……. |
要根據朝代或者做者尋找詩,都很簡單,好比「select 詩詞全文 from 詩詞表where做者=‘李白’」,若是數據不少,查詢速度很慢,怎麼辦?咱們能夠在對應的查詢字段上創建索引加速查詢。
可是若是咱們如今有個需求:要求找到包含「望」字的詩詞怎麼辦?用
「select 詩詞全文 from 詩詞表 where 詩詞全文 like‘%望%’」,這個意味着
要掃描庫中的詩詞全文字段,逐條比對,找出全部包含關鍵詞「望」字的記錄,。
基本上,數據庫中通常的 SQL 優化手段都是用不上的。數量少,大概性能還能接受,若是數據量稍微大點,就徹底沒法接受了,更況且在互聯網這種海量數據的狀況下呢?
怎麼解決這個問題呢,用倒排索引。
好比如今有:
蜀道難(唐)李白 蜀道之難難於上青天,側身西望長諮嗟。
靜夜思(唐)李白 舉頭望明月,低頭思故鄉。
春臺望(唐)李隆基 暇景屬三春,高臺聊四望。
鶴沖天(宋)柳永 黃金榜上,偶失龍頭望。明代暫遺賢,如何向?未遂風雲便,爭不恣狂蕩。何必論得喪?才子詞人,自是白衣卿相。煙花巷陌,依約丹青屏障。
幸有意中人,堪尋訪。且恁偎紅翠,風流事,生平暢。青春都一餉。忍把浮名,換了淺斟低唱!
都有望字,因而咱們能夠這麼保存
序號 |
關鍵字 |
蜀道難 |
靜夜思 |
春臺望 |
鶴沖天 |
1 |
望 |
有 |
有 |
有 |
有 |
|
|
|
|
|
若是查哪一個詩詞中包含上,怎麼辦,上述的表格能夠繼續填入新的記錄
序號 |
關鍵字 |
蜀道難 |
靜夜思 |
春臺望 |
鶴沖天 |
1 |
望 |
有 |
有 |
有 |
有 |
2 |
上 |
有 |
|
|
有 |
其實,上述詩詞的中每一個字均可以做爲關鍵字,而後創建關鍵字和文檔之間的對應關係,也就是標識關鍵字被哪些文檔包含。
因此,倒排索引就是,將文檔中包含的關鍵字所有提取處理,而後再將關鍵字和文檔之間的對應關係保存起來,最後再對關鍵字自己作索引排序。用戶在檢索某一個關鍵字是,先對關鍵字的索引進行查找,再經過關鍵字與文檔的對應關係找到所在文檔。
在存儲在關係型數據庫中的數據,須要咱們事先分析將數據拆分爲不一樣的字段,而在 es 這類的存儲中,須要應用程序根據規則自動提取關鍵字,並造成對應關係。
這些預先提取的關鍵字,在全文檢索領域通常被稱爲 term(詞項),文檔的詞項提取在 es 中被稱爲文檔分析,這是全文檢索很核心的過程,必需要區分哪些是詞項,哪些不是,好比不少場景下,apple和 apples 是同一個東西,望和看實際上是同一個動做。
Elasticsearch 中比較關鍵的基本概念有索引、文檔、映射、映射類型、文檔字段概念,爲了方便理解,能夠和關係數據庫中的相關概念進行個比對:
Elasticsearch 索引是映射類型的容器。一個 Elasticsearch 索引很是像關係型世界的數據庫,是獨立的大量文檔集合。
固然在底層,確定用到了倒排索引,最基本的結構就是「keyword」和「PostingList」,Posting list就是一個 int的數組,存儲了全部符合某個 term的文檔 id。
另外,這個倒排索引相比特定詞項出現過的文檔列表,會包含更多其它信息。
它會保存每個詞項出現過的文檔總數,在對應的文檔中一個具體詞項出現的總次數,詞項在文檔中的順序,每一個文檔的長度,全部文檔的平均長度等等相關信息。
文檔是 es 中全部可搜索數據的最小單位,好比日誌文件中的日誌項、一部電影的具體信息等等。
文檔會被序列化 JSON格式保存到 ElasticSearch 中,JSON 對象由字段組成,每一個字段都有對象的字段類型(字符串,數值,布爾,日期,二進制,範圍類型)。
同時每一個文檔都有一個 Unique ID,能夠本身指定 ID,或者經過 ElasticSearch 自動生成。
因此嚴格來講,es 中存儲的文檔是一種半結構化的數據。
映射(mapping)定義了每一個字段的類型、字段所使用的分詞器等。
get /enjoy_test/_mapping
能夠顯式映射,由咱們在索引映射中進行預先定義;也能夠動態映射,在添加文檔的時候,由 es 自動添加到索引,這個過程不須要事先在索引進行字段數據類型匹配等等,es 會本身推斷數據類型。
既然說到了字段類型,固然就離不開字段的數據類型了。
文檔中的一個字段 field就至關於關係型數據庫中的一列 column,那麼它確定有數據類型,es 提供的數據類型包括至少有:
核心數據類型
# 字符串類型:string,字符串類還可被分爲 text和 keyword 類型,若是咱們讓 es自動映射數據,那麼 es 會把字符串定義爲 text,而且還加了一個 keyword類型字段。
text文本數據類型,用於索引全文值的字段。使用文本數據類型的字段,它們會被分詞,在索引以前將字符串轉換爲單個術語的列表(倒排索引),分詞過程容許 ES 搜索每一個全文字段中的單個單詞。什麼狀況適合使用 text,只要不具有惟一性的字符串通常均可以使用 text。
keyword,關鍵字數據類型,用於索引結構化內容的字段。使用 keyword 類型的字段,其不會被分析,給什麼值就原封不動地按照這個值索引,因此關鍵字字段只能按其確切值進行搜索。什麼狀況下使用 keyword,具備惟一性的字符串,例如:電子郵件地址、MAC 地址、身份證號、狀態代碼...等等。
# 數字型數據類型:long、integer、short、byte、double、float
# 日期類型:date
# 布爾類型:boolean
複雜數據類型
# 數組:無需專門的數據類型
# 對象數據類型:單獨的 JSON對象
# 嵌套數據類型:nested,關於 JSON對象的數組
地理數據類型:
# 地理點數據類型
# 地理形狀數據類型
專門數據類型:
# IPv4 數據類型
# 單詞計數數據類型 token_count
咱們結合前面的映射來看看:
建立一個新的索引:put /open-soft
顯式映射:
put /open-soft/_mapping
{
"properties" : {
"corp" : {
"type" : "text"
},
"lang" : {
"type" : "text"
},
"name" : {
"type" : "text"
}
索引或者說入庫一個文檔,注意這個文檔的字段,比咱們顯示映射的字段要多個 star字段:
put /open-soft/_doc/1
{
"name": "Apache Hadoop",
"lang": "Java",
"corp": "Apache",
"stars":200
}
經過 get /open-soft/_mapping,咱們能夠看到 es 自動幫咱們新增了 stars這個字段。
修改映射,增長一個新的字段:
put /open-soft/_mapping
{
"properties" : {
"year" : {
"type" : "integer"
}
}
}
不須要特殊配置,一個字段若是被配置爲基本數據類型,就是天生支持數組類型的。任何字段均可以有 0個或多個值,可是在一個數組中數據類型必須同樣。
好比:
put /open-soft/_doc/2
{
"name": ["Apache Activemq","Activemq Artemis"],
"lang": "Java",
"corp": "Apache",
"stars":[500,200]
}
是沒問題的,可是若是:
put /open-soft/_doc/3
{
"name": ["Apache Kafka"],
"lang": "Java",
"corp": "Apache",
"stars":[500,"kafka"]
}
則會出錯。
JSON文檔是有層次結構的,一個文檔可能包含其餘文檔,若是一個文檔包含其餘文檔,那麼該文檔值是對象類型,其數據類型是對象。固然 ElasticSearch中是沒有所謂對象類型的,好比:
put /open-soft/_doc/object
{
"name": ["Apache ShardingSphere"],
"lang": "Java",
"corp": "JingDong",
"stars":400,
"address":{
"city":"BeiJing",
"country":"亦莊"
}
}
對象類型能夠在定義索引的映射關係時進行指定。
若是說數組容許你使用同一個設置索引多項數據,那麼多數據類型容許使用不一樣的設置,對同一項數據索引屢次。帶來的好處就是能夠同一文本有多種不一樣的索引方式,好比一個字符串類型的字段,能夠使用 text類型作全文檢索,使用keyword 類型作聚合和排序。咱們能夠看到 es 的動態映射生成的字段類型裏,每每字符串類型都使用了多數據類型。固然,咱們同樣也能夠本身定義:
put /open-soft/_mapping
{
"properties" : {
"name" : {
"type" : "text",
"fields":{
"raw":{
"type" : "keyword"
},
"length":{
"type" : "token_count",
"analyzer":"standard"
}
}
}
}
}
在上面的代碼裏,咱們使用"fields"就把 name字段擴充爲多字段類型,爲name新增了兩個子字段 raw和 length,raw設置類型爲 keyword,length 設置類型爲 token_count,告訴 es 這個字段在保存還須要作詞頻統計。
經過 fields字段設置的子字段 raw 和 length,在咱們添加文檔時,並不須要單獨設置值,他們 name共享相同的值,只是 es 會以不一樣的方式處理字段值。
一樣在檢索文檔的時候,它們也不會顯示在結果中,因此它們通常都是在檢索中以查詢條件的形式出現,以減小檢索時的性能開銷。
在上面的代碼裏出現了analyzer這個詞,這是什麼?這個叫字段參數,和 type同樣,能夠用來對字段進行配置。經常使用的字段參數和做用以下:
analyzer
指定分詞器。elasticsearch是一款支持全文檢索的分佈式存儲系統,對於 text類型的字段,首先會使用分詞器進行分詞,而後將分詞後的詞根一個一個存儲在倒排索引中,後續查詢主要是針對詞根的搜索。
analyzer該參數能夠在每一個查詢、每一個字段、每一個索引中使用,其優先級以下(越靠前越優先):
一、字段上定義的分詞器
二、索引配置中定義的分詞器
三、默認分詞器(standard)
normalizer
規範化,主要針對 keyword 類型,在索引該字段或查詢字段以前,能夠先對原始數據進行一些簡單的處理,而後再將處理後的結果當成一個詞根存入倒排索引中,默認爲 null,好比:
PUT index
{
"settings": {
"analysis": {
"normalizer": {
"my_normalizer": { // 1
"type": "custom",
"char_filter": [],
"filter": ["lowercase", "asciifolding"] // 2
}
}
}
},
"mappings": {
"_doc": {
"properties": {
"foo": {
"type": "keyword",
"normalizer": "my_normalizer" // 3
}
}
}
}
}
代碼 1:首先在 settings中的 analysis 屬性中定義 normalizer。
代碼 2:設置標準化過濾器,示例中的處理器爲小寫、asciifolding。
代碼 3:在定義映射時,若是字段類型爲 keyword,能夠使用 normalizer
引用定義好的 normalizer
boost
權重值,能夠提高在查詢時的權重,對查詢相關性有直接的影響,其默認值爲1.0。其影響範圍爲詞根查詢(team query),對前綴、範圍查詢。5.0 版本後已廢止。
coerce
數據不老是咱們想要的,因爲在轉換 JSON body 爲真正 JSON 的時候,整型數字5有可能會被寫成字符串"5"或者浮點數 5.0,這個參數能夠將數值不合法的部分去除。默認爲 true。
例如:將字符串會被強制轉換爲整數、浮點數被強制轉換爲整數。
例如存在以下字段類型:
"number_one": {
"type": "integer"
}
聲明 number_one字段的類型爲數字類型,那是否容許接收「6」字符串形式的數據呢?由於在 JSON中,「6」用來賦給 int類型的字段,也是能接受的,默認 coerce 爲 true,表示容許這種賦值,但若是 coerce 設置爲 false,此時 es只能接受不帶雙引號的數字,若是在 coerce=false 時,將「6」賦值給 number_one時會拋出類型不匹配異常。
copy_to
copy_to參數容許您建立自定義的_all字段。換句話說,多個字段的值能夠複製到一個字段中。
例如,first_name和 last_name 字段能夠複製到 full_name 字段以下:
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"first_name": {
"type": "text",
"copy_to": "full_name"
},
"last_name": {
"type": "text",
"copy_to": "full_name"
表示字段 full_name的值來自 first_name + last_name。
關於 copy_to重點說明:
一、字段的複製是原始值。
二、同一個字段能夠複製到多個字段,寫法以下:「copy_to」: [ 「field_1」,
「field_2」]
Doc values 的存在是由於倒排索引只對某些操做是高效的。倒排索引的優點在於查找包含某個項的文檔,而對於從另一個方向的相反操做並不高效,即:肯定哪些項是否存在單個文檔裏,聚合須要這種次級的訪問模式。
對於如下倒排索引:
若是咱們想要得到全部包含 檔的詞的完整列表,倒排索引是根據項來排序的,因此咱們首先在詞 ,而後掃描全部列,找到包含 brown 的文檔。咱們能夠快速 和 包含 brown 這個 token。
而後,對於聚合部分,咱們須要找到 Doc_1 和 Doc_2 裏全部惟一的詞項。用倒排索引作這件事情代價很高:咱們會迭代索引裏的每一個詞項並收集 Doc_1 和 Doc_2 列裏面 token。這很慢並且難以擴展:隨着詞項和文檔的數量增長,執行時間也會增長。
Doc values 經過轉置二者間的關係來解決這個問題。倒排索引將詞項映射到包含它們的文檔,doc values 將文檔映射到它們包含的詞項:
當數據被轉置以後,想要收集到 Doc_1 和 Doc_2 的惟一 token 會很是容易。得到每一個文檔行,獲取全部的詞項,而後求兩個集合的並集。
doc_values缺省是 true,便是開啓的,而且只適用於非 text類型的字段。
是否容許動態的隱式增長字段。在執行 index api 或更新文檔 API 時,對於_source字段中包含一些原先未定義的字段採起的措施,根據 dynamic 的取值,會進行不一樣的操做:
true,默認值,表示新的字段會加入到類型映射中。
false,新的字段會被忽略,即不會存入_souce字段中,即不會存儲新字段,也沒法經過新字段進行查詢。
strict,會顯示拋出異常,須要新使用 put mapping api 先顯示增長字段映射。
是否創建索引,默認狀況下爲 true,es 會嘗試爲你索引全部的字段,但有時候某些類型的字段,無需創建索引,只是用來存儲數據便可。也就是說,
ELasticseaech默認會索引全部的字段,enabled設爲 false的字段,elasicsearch 會跳過字段內容,該字段只能從_source 中獲取,可是不可搜。只有映射類型(type)和object 類型的字段能夠設置 enabled屬性。
表示是否提早加載全局順序號。Global ordinals 是一個創建在 doc values 和fielddata基礎上的數據結構, 它爲每個精確詞按照字母順序維護遞增的編號。每個精確詞都有一個獨一無二的編號 而且 精確詞 A 小於精確詞 B 的編號.Global ordinals 只支持 keyword 和 text 型字段,在 keyword 字段中, 默認是啓用的 而在 text 型字段中 只有 fielddata 和相關屬性開啓的狀態下才是可用的。
爲了解決排序與聚合,elasticsearch 提供了 doc_values 屬性來支持列式存儲,但doc_values 不支持 text 字段類型。由於 text 字段是須要先分析(分詞),會影響 doc_values 列式存儲的性能。
es 爲了支持 text字段高效排序與聚合,引入了一種新的數據結構(fielddata),使用內存進行存儲。默認構建時機爲第一次聚合查詢、排序操做時構建,主要存儲倒排索引中的詞根與文檔的映射關係,聚合,排序操做在內存中執行。所以fielddata須要消耗大量的 JVM 堆內存。一旦 fielddata加載到內存後,它將永久存在。
一般狀況下,加載 fielddata 是一個昂貴的操做,故默認狀況下,text 字段的字段默認是不開啓 fielddata機制。在使用 fielddata 以前請慎重考慮爲何要開啓fielddata。
在 JSON文檔中,日期表示爲字符串。Elasticsearch 使用一組預先配置的格式來識別和解析這些字符串,並將其解析爲 long類型的數值(毫秒),支持自定義格式,也有內置格式。
好比:
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"date": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
}}}}}
elasticsearch爲咱們內置了大量的格式,以下:
epoch_millis
時間戳,單位,毫秒,範圍受限於 Java Long.MIN_VALUE和 Long.MAX_VALUE。
epoch_second
時間戳,單位,秒,範圍受限於 Java的限制 Long.MIN_VALUE 並 Long.
MAX_VALUE 除以 1000(一秒中的毫秒數)。
date_optional_time或者 strict_date_optional_time
日期必填,時間可選,其支持的格式以下:
date-opt-time = date-element ['T' [time-element] [offset]]
date-element = std-date-element | ord-date-element | week-date-element
std-date-element = yyyy ['-' MM ['-' dd]]
ord-date-element = yyyy ['-' DDD]
week-date-element = xxxx '-W' ww ['-' e]
time-element = HH [minute-element] | [fraction]
minute-element = ':' mm [second-element] | [fraction]
second-element = ':' ss [fraction]
好比"yyyy-MM-dd"、"yyyyMMdd"、"yyyyMMddHHmmss"、
"yyyy-MM-ddTHH:mm:ss"、"yyyy-MM-ddTHH:mm:ss.SSS"、
"yyyy-MM-ddTHH:mm:ss.SSSZ"格式,不支持經常使用的"yyyy-MM-dd HH:mm:ss"等格式。
注意,"T"和"Z"是固定的字符。
tips:若是看到「strict_」前綴的日期格式要求,表示 date_optional_time 的嚴格級別,這個嚴格指的是年份、月份、天必須分別以 4位、2 位、2 位表示,不足兩位的話第一位需用 0補齊。
basic_date
其格式表達式爲 :yyyyMMdd
basic_date_time
其格式表達式爲:yyyyMMdd’T’HHmmss.SSSZ
basic_date_time_no_millis
其格式表達式爲:yyyyMMdd’T’HHmmssZ
basic_ordinal_date
4位數的年 + 3 位(day of year),其格式字符串爲 yyyyDDD
basic_ordinal_date_time
其格式字符串爲 yyyyDDD’T’HHmmss.SSSZ
basic_ordinal_date_time_no_millis
其格式字符串爲 yyyyDDD’T’HHmmssZ
basic_time
其格式字符串爲 HHmmss.SSSZ
basic_time_no_millis
其格式字符串爲 HHmmssZ
basic_t_time
其格式字符串爲’T’HHmmss.SSSZ
basic_t_time_no_millis
其格式字符串爲’T’HHmmssZ
basic_week_date
其格式字符串爲 xxxx’W’wwe,4 爲年 ,而後用’W’, 2 位 week of year(所在年裏周序號)1位 day of week。
basic_week_date_time
其格式字符串爲 xxxx’W’wwe’T’HH:mm:ss.SSSZ.
basic_week_date_time_no_millis
其格式字符串爲 xxxx’W’wwe’T’HH:mm:ssZ.
date
其格式字符串爲 yyyy-MM-dd
date_hour
其格式字符串爲 yyyy-MM-dd’T’HH
date_hour_minute
其格式字符串爲 yyyy-MM-dd’T’HH:mm
date_hour_minute_second
其格式字符串爲 yyyy-MM-dd’T’HH:mm:ss
date_hour_minute_second_fraction
其格式字符串爲 yyyy-MM-dd’T’HH:mm:ss.SSS
date_hour_minute_second_millis
其格式字符串爲 yyyy-MM-dd’T’HH:mm:ss.SSS
date_time
其格式字符串爲 yyyy-MM-dd’T’HH:mm:ss.SSS
date_time_no_millis
其格式字符串爲 yyyy-MM-dd’T’HH:mm:ss
hour
其格式字符串爲 HH
hour_minute
其格式字符串爲 HH:mm
hour_minute_second
其格式字符串爲 HH:mm:ss
hour_minute_second_fraction
其格式字符串爲 HH:mm:ss.SSS
hour_minute_second_millis
其格式字符串爲 HH:mm:ss.SSS
ordinal_date
其格式字符串爲 yyyy-DDD,其中 DDD爲 day of year。
ordinal_date_time
其格式字符串爲 yyyy-DDD‘T’HH:mm:ss.SSSZZ,其中 DDD爲 day of year。
ordinal_date_time_no_millis
其格式字符串爲 yyyy-DDD‘T’HH:mm:ssZZ
time
其格式字符串爲 HH:mm:ss.SSSZZ
time_no_millis
其格式字符串爲 HH:mm:ssZZ
t_time
其格式字符串爲’T’HH:mm:ss.SSSZZ
t_time_no_millis
其格式字符串爲’T’HH:mm:ssZZ
week_date
其格式字符串爲 xxxx-'W’ww-e,4 位年份,ww 表示 week of year,e 表示 dayof week。
week_date_time
其格式字符串爲 xxxx-'W’ww-e’T’HH:mm:ss.SSSZZ
week_date_time_no_millis
其格式字符串爲 xxxx-'W’ww-e’T’HH:mm:ssZZ
weekyear
其格式字符串爲 xxxx
weekyear_week
其格式字符串爲 xxxx-'W’ww,其中 ww 爲 week of year。
weekyear_week_day
其格式字符串爲 xxxx-'W’ww-e,其中 ww 爲 week of year,e爲 day of week。
year
其格式字符串爲 yyyy
year_month
其格式字符串爲 yyyy-MM
year_month_day
其格式字符串爲 yyyy-MM-dd
ignore_above用於指定字段索引和存儲的長度最大值,超過最大值的會被忽略。
ignore_malformed能夠忽略不規則數據,對於 login 字段,有人可能填寫的是date類型,也有人填寫的是郵件格式。給一個字段索引不合適的數據類型發生異常,致使整個文檔索引失敗。若是 ignore_malformed參數設爲 true,異常會被忽
略,出異常的字段不會被索引,其它字段正常索引。
index
index 屬性指定字段是否索引,不索引也就不可搜索,取值能夠爲 true 或者false,缺省爲 true。
index_options
index_options 控制索引時存儲哪些信息到倒排索引中,,用於搜索和突出顯示目的。
docs 只存儲文檔編號
freqs 存儲文檔編號和詞項頻率。
positions 文檔編號、詞項頻率、詞項的位置被存儲
offsets 文檔編號、詞項頻率、詞項的位置、詞項開始和結束的字符位置都被存儲。
fields
fields可讓同一文本有多種不一樣的索引方式,好比一個 String 類型的字段,能夠使用 text類型作全文檢索,使用 keyword 類型作聚合和排序。
norms
norms參數用於標準化文檔,以便查詢時計算文檔的相關性。norms 雖然對評分有用,可是會消耗較多的磁盤空間,若是不須要對某個字段進行評分,最好不要開啓 norms。
null_value
通常來講值爲 null的字段不索引也不能夠搜索,null_value參數可讓值爲null的字段顯式的可索引、可搜索。
PUT my_index
{
"mappings": {
"my_type": {
"properties": {
"status_code": {
"type": "keyword",
"null_value": "NULL"
}
}
}
}
}
GET my_index/_search
{
"query": {
"term": {
"status_code": "NULL"
}
}
}
文檔 1能夠被搜索到,由於 status_code的值爲 null,文檔 2 不能夠被搜索到,由於 status_code爲空數組,可是不是 null。
position_increment_gap
文本數組元素之間位置信息添加的額外值。
舉例,一個字段的值爲數組類型:"names": [ "John Abraham", "Lincoln Smith"]爲了區別第一個字段和第二個字段,Abraham和 Lincoln在索引中有一個間
距,默認是 100。例子以下,這是查詢」Abraham Lincoln」是查不到的:
PUT my_index/groups/1
{
"names": [ "John Abraham", "Lincoln Smith"]
}
GET my_index/groups/_search
{
"query": {
"match_phrase": {
"names": {
"query": "Abraham Lincoln"
}}}}
指定間距大於 10 0 能夠查詢到:
GET my_index/groups/_search
{
"query": {
"match_phrase": {
"names": {
"query": "Abraham Lincoln",
"slop": 101
}}}}
想要調整這個值,在 mapping中經過 position_increment_gap 參數指定間距便可。
properties
Object或者 nested類型,下面還有嵌套類型,能夠經過 properties 參數指定。
好比:
PUT my_index
{
"mappings": {
"my_type": {
"properties": {
"manager": {
"properties": {
"age": { "type": "integer" },
"name": { "type": "text" }
}
},
"employees": {
"type": "nested",
"properties": {
"age": { "type": "integer" },
"name": { "type": "text" }
}}}}}}
對應的文檔結構:
PUT my_index/my_type/1
{
"region": "US",
"manager": {
"name": "Alice White",
"age": 30
},
"employees": [
{
"name": "John Smith",
"age": 34
},
{
"name": "Peter Brown",
"age": 26
}
]
}
search_analyzer
一般,在索引時和搜索時應用相同的分析器,以確保查詢中的術語與反向索引中的術語具備相同的格式,若是想要在搜索時使用與存儲時不一樣的分詞器,則使用 search_analyzer屬性指定,一般用於 ES 實現即時搜索(edge_ngram)。
similarity
指定類似度算法,其可選值:
BM25
當前版本的默認值,使用 BM25算法。
classic
使用 TF/IDF算法,曾經是 es,lucene 的默認類似度算法。
boolean
一個簡單的布爾類似度,當不須要全文排序時使用,而且分數應該只基於查詢條件是否匹配。布爾類似度爲術語提供了一個與它們的查詢boost相等的分數。
store
默認狀況下,字段值被索引以使其可搜索,但它們不存儲。這意味着能夠查詢字段,但沒法檢索原始字段值。一般這並不重要。字段值已是_source字段的一部分,該字段默認存儲。若是您只想檢索單個字段或幾個字段的值,而不是整個_source,那麼這能夠經過字段過濾上下文 source filting context來實現。
在某些狀況下,存儲字段是有意義的。例如,若是您有一個包含標題、日期和很是大的內容字段的文檔,您可能只想檢索標題和日期,而不須要從大型_source字段中提取這些字段,能夠將標題和日期字段的 store定義爲 ture。
term_vector
Term vectors 包含分析過程產生的索引詞信息,包括:
索引詞列表
每一個索引詞的位置(或順序)
索引詞在原始字符串中的原始位置中的開始和結束位置的偏移量。
term vectors 會被存儲,索引它能夠做爲一個特使的文檔返回。
term_vector可取值:
不存儲 term_vector信息,默認值。
yes
只存儲字段中的值。
with_positions
存儲字段中的值與位置信息。
with_offsets
存儲字段中的值、偏移量
with_positions_offsets
存儲字段中的值、位置、偏移量信息。
元字段 meta-fields
一個文檔根據咱們定義的業務字段保存有數據以外,它還包含了元數據字段
(meta-fields)。元字段不須要用戶定義,在任一文檔中都存在,有點相似於數據庫的表結構數據。在名稱上有個顯著的特徵,都是如下劃線「_」開頭。
咱們能夠看看:get /open-soft/_doc/1
大致分爲五種類型:身份(標識)元數據、索引元數據、文檔元數據、路由元數據以及其餘類型的元數據,固然不是每一個文檔這些元字段都有的。
身份(標識)元數據
_index:文檔所屬索引 , 自動被索引,可被查詢,聚合,排序使用,或者腳本里訪問
_type:文檔所屬類型,自動被索引,可被查詢,聚合,排序使用,或者腳本里訪問
_id:文檔的惟一標識,建索引時候傳入 ,不被索引,可經過_uid被查詢,腳本里使用,不能參與聚合或排序
_uid:由_type和_id字段組成,自動被索引 ,可被查詢,聚合,排序使用,或者腳本里訪問,6.0.0版本後已廢止。
索引元數據
_all:自動組合全部的字段值,以空格分割,能夠指定分器詞索引,可是整個值不被存儲,因此此字段僅僅能被搜索,不能獲取到具體的值。6.0.0版本後已廢止。
_field_names:索引了每一個字段的名字,能夠包含 null值,能夠經過 exists查詢或 missing查詢方法來校驗特定的字段
文檔元數據
_source : 一個 doc的原生的 json 數據,不會被索引,用於獲取提取字段值,啓動此字段,索引體積會變大,若是既想使用此字段又想兼顧索引體積,能夠開啓索引壓縮。
_source是能夠被禁用的,不過禁用以後部分功能再也不支持,這些功能包括:部分 update api、運行時高亮搜索結果
索引重建、修改 mapping以及分詞、索引升級
debug查詢或者聚合語句
索引自動修復
_size:整個_source 字段的字節數大小,須要單獨安裝一個 mapper-size插件才能展現。
路由元數據
_routing:一個 doc能夠被路由到指定的 shard上。
_meta:通常用來存儲應用相關的元信息。
其餘
例如:
put /open-soft/_mapping
{
"_meta": {
"class": "cn.enjoyedu.User",
"version": {"min": "1.0", "max": "1.3"}
}
}
在 es 中,索引和文檔是 REST 接口操做的最基本資源,因此對索引和文檔的管理也是咱們必需要知道的。索引通常是以索引名稱出如今 REST請求操做的資源路徑上,而文檔是以文檔 ID 爲標識出如今資源路徑上。映射類型_doc 也能夠認爲是一種資源,但在 es7 中廢除了映射類型,因此能夠_doc 也視爲一種接口。
索引的管理
在前面的學習中咱們已經知道,GET 用來獲取資源,PUT 用來更新資源,DELETE用來刪除資源。因此對索引,GET用來查看索引,PUT用來建立索引,DELETE用來刪除索引,還有一個 HEAD 請求,用來檢驗索引是否存在。除此以外,對索引的管理還有
列出全部索引
GET /_cat/indices?v
關閉索引和打開
POST /open-soft/_close、、
除了刪除索引,還能夠選擇關閉它們。若是關閉了一個索引,就沒法經過Elasticsearch來讀取和寫人其中的數據,直到再次打開它。
在現實世界中,最好永久地保存應用日誌,以防要查看好久以前的信息。另外一方面,在 Elasticsearch 中存放大量數據須要增長資源。對於這種使用案例,關閉舊的索引很是有意義。你可能並不須要那些數據,可是也不想刪除它們。
一旦索引被關閉,它在 Elasticsearch 內存中惟-的痕跡是其元數據,如名字
以及分片的位置。若是有足夠的磁盤空間,並且也不肯定是否須要在那個數據中再次搜索,關閉索引要比刪除索引更好。關閉它們會讓你很是安心,永遠能夠從新打開被關閉的索引,而後在其中再次搜索。
從新打開 POST /open-soft/_open
配置索引
經過 settings參數配置索引,索引的全部配置項都以「index」開頭。索引的管理分爲靜態設置和動態設置兩種。
靜態設置
只能在索引建立時或在狀態爲 closed index(閉合索引)上設置,主要配置索引主分片、壓縮編碼、路由等相關信息
index.number_of_shards主分片數,默認爲 5.只能在建立索引時設置,不能修改
index.shard.check_on_startup 是否應在索引打開前檢查分片是否損壞,當檢查到分片損壞將禁止分片被打開。false:默認值;checksum:檢查物理損壞;true:檢查物理和邏輯損壞,這將消耗大量內存和 CPU;fix:檢查物理和邏輯損壞。
有損壞的分片將被集羣自動刪除,這可能致使數據丟失
index.routing_partition_size 自定義路由值能夠轉發的目的分片數。默認爲 1,只能在索引建立時設置。此值必須小於 index.number_of_shards
index.codec 默認使用 LZ4壓縮方式存儲數據,也能夠設置爲
best_compression,它使用 DEFLATE 方式以犧牲字段存儲性能爲代價來得到更高的壓縮比例。
如:
put test1{
"settings":{
"index.number_of_shards":3,
"index.codec":"best_compression"
}
}
動態設置
經過接口「_settings」進行,同時查詢配置也經過這個接口進行,好比:get _settings
get /open-soft/_settings
get /open-soft,test1/_settings
配置索引則經過:
put test1/_settings
{
"refresh_interval":"2s"
}
經常使用的配置參數以下:
index.number_of_replicas 每一個主分片的副本數。默認爲 1
index.auto_expand_replicas 基於可用節點的數量自動分配副本數量,默認爲false(即禁用此功能)
index.refresh_interval 執行刷新操做的頻率。默認爲 1s。能夠設置爲 -1 以禁用刷新。
index.max_result_window 用於索引搜索的 from+size 的最大值。默認爲10000
index.blocks.read_only 設置爲 true 使索引和索引元數據爲只讀,false 爲容許寫入和元數據更改。
index.blocks.read 設置爲 true 可禁用對索引的讀取操做
index.blocks.write 設置爲 true 可禁用對索引的寫入操做
index.blocks.metadata 設置爲 true 可禁用索引元數據的讀取和寫入
index.max_refresh_listeners 索引的每一個分片上可用的最大刷新偵聽器數index.max_docvalue_fields_search 一次查詢最多包含開啓 doc_values 字段
的個數,默認爲 100
index.max_script_fields 查詢中容許的最大 script_fields數量。默認爲 32。
index.max_terms_count 能夠在 terms 查詢中使用的術語的最大數量。默認爲65536。
index.routing.allocation.enable 控制索引分片分配。All(全部分片)、primaries(主分片)、new_primaries(新建立分片)、none(不分片)
index.routing.rebalance.enable 索引的分片從新平衡機制。all、primaries、replicas、none
index.gc_deletes 文檔刪除後(刪除後版本號)還能夠存活的週期,默認
爲 60s
index.max_regex_length用於正在表達式查詢(regex query)正在表達式長度,默認爲 1000
配置映射
經過_mapping 接口進行,在咱們前面的章節中,已經展現過了。
get /open-soft/_mapping
或者只看某個字段的屬性:
get /open-soft/_mapping/field/lang
修改映射,固然就是經過 put或者 post方法了。可是要注意,已經存在的映射只能添加字段或者字段的多類型。可是字段建立後就不能刪除,大多數參數也不能修改,能夠改的是 ignore_above。因此設計索引時要作好規劃,至少初始時的必要字段要規劃好。
增長文檔
增長文檔,咱們在前面的章節已經知道了,好比:
put /open-soft/_doc/1
{
"name": "Apache Hadoop",
"lang": "Java",
"corp": "Apache",
"stars":200
}
若是增長文檔時,在 Elasticsearch中若是有相同 ID的文檔存在,則更新此文檔,好比執行
put /open-soft/_doc/1
{
"name": "Apache Hadoop2",
"lang": "Java8",
"corp": "Apache",
"stars":300
}
則會發現已有文檔的內容被更新了
文檔的 id
當建立文檔的時候,若是不指定 ID,系統會自動建立 ID。自動生成的 ID 是一個不會重複的隨機數。使用 GUID 算法,能夠保證在分佈式環境下,不一樣節點同一時間建立的_id必定是不衝突的。好比:
post /open-soft/_doc
{
"message":"Hello"
}
查詢文檔
get /open-soft/_doc/
更新文檔
前面咱們用 put方法更新了已經存在的文檔,可是能夠看見他是總體更新文檔,若是咱們要更新文檔中的某個字段怎麼辦?須要使用_update接口。
post /open-soft/_update/1/
{
"doc":{
"year": 2016
}
}
若是文檔中存在 year字段,更新 year 字段的值,若是不存在 year 字段,則會新增 year字段,並將值設爲 2016。
update 接口在文檔不存在時提示錯誤,若是但願在文檔不存在時建立文檔,則能夠在請求中添加 upsert參數或 doc_as_upsert 參數,例如:
POST /open-soft/_update/5
{
"doc": {
"year": "2020"
},
"upsert":{
"name" : "Enjoyedu Framework",
"corp" : "enjoyedu "
}
}
或
POST /open-soft/_update/6
{
"doc": {
"year": "2020"
},
"doc_as_upsert" : true
}
upsert參數定義了建立新文檔使用的文檔內容,而 doc_as_upsert 參數的含義是直接使用 doc參數中的內容做爲建立文檔時使用的文檔內容。
刪除文檔
delete /open-soft/_doc/1
爲了方便咱們學習,咱們導入 kibana 爲咱們提供的範例數據。
目前爲止,咱們已經探索瞭如何將數據放入 Elasticsearch,如今來討論下如何將數據從 Elasticsearch中拿出來,那就是經過搜索。畢竟,若是不能搜索數據,那麼將其放入搜索引擎的意義又何在呢?幸運的是,Elasticsearch 提供了豐富的接口來搜索數據,涵蓋了 Lucene 全部的搜索功能。由於 Elasticsearch容許構建搜索請求的格式很靈活,請求的構建有無限的可能性。要了解哪些查詢和過濾器的組合適用於你的數據,最佳的方式就是進行實驗,所以不要懼怕在項目的數據上嘗試這些組合,這樣才能弄清哪些更適合你的需求。
全部的 REST搜索請求使用_search 接口,既能夠是 GET請求,也能夠是 POST請求,也能夠經過在搜索 URL 中指定索引來限制範圍。
_search 接口有兩種請求方法,一種是基於 URI 的請求方式,另外一種是基於請求體的方式,不管哪一種,他們執行的語法都是基於 DSL(ES 爲咱們定義的查詢語言,基於 JSON的查詢語言),只是形式上不一樣。咱們會基於請求體的方式來學習。好比說:
get kibana_sample_data_flights/_search
{
"query":{
"match_all":{}
}
}
或
get kibana_sample_data_flights/_search
{
"query":{
"match_none":{}
}
}
固然上面的查詢沒什麼太多的用處,由於他們分別表明匹配全部和全不匹配。
因此咱們常常要使用各類語法來進行查詢,一旦選擇了要搜索的索引,就須要配置搜索請求中最爲重要的模塊。這些模塊涉及文檔返回的數量,選擇最佳的文檔返回,以及配置不但願哪些文檔出如今結果中等等。
■ query-這是搜索請求中最重要的組成部分,它配置了基於評分返回的最佳文檔,也包括了你不但願返回哪些文檔。
■ size-表明了返回文檔的數量。
■ from-和 size 一塊兒使用,from 用於分頁操做。須要注意的是,爲了肯定第2頁的 10 項結果,Elasticsearch 必需要計算前 20 個結果。若是結果集合不斷增長,獲取某些靠後的翻頁將會成爲代價高昂的操做。
■ _source指定_ source 字段如何返回。默認是返回完整的_ source字段。
經過配置_ source,將過濾返回的字段。若是索引的文檔很大,並且無須結果中的所有內容,就使用這個功能。請注意,若是想使用它,就不能在索引映射中關閉_source 字段。
■ sort默認的排序是基於文檔的得分。若是並不關心得分,或者指望許多文檔的得分相同,添加額外的 sort將幫助你控制哪些文檔被返回。
命名適宜的 from和 size字段,用於指定結果的開始點,以及每「頁"結果的數量。舉個例子,若是發送的 from 值是 7,size值是 5,那麼 Elasticsearch 將返回第八、九、十、11 和 12項結果(因爲 from 參數是從 0開始,指定 7 就是從第 8項結果開始)。若是沒有發送這兩個參數,Elasticsearch 默認從第一項結果開始(第 0 項結果),在回覆中返回 10項結果。
例如
get kibana_sample_data_flights/_search
{
"from":100,
"size":20,
"query":{
"term":{
"DestCountry":"CN"
}
}
}
可是注意,from與 size 的和不能超過 index. max_result_window 這個索引配置項設置的值。默認狀況下這個配置項的值爲 10000,因此若是要查詢 10000 條之後的文檔,就必需要增長這個配置值。例如,要檢索第 10000 條開始的 200條數據,這個參數的值必需要大於 10200,不然將會拋出相似「Result window is toolarge'的異常。
因而可知,Elasticsearch 在使用 from 和 size處理分頁問題時會將全部數據所有取出來,而後再截取用戶指定範圍的數據返回。因此在查詢很是靠後的數據時,即便使用了 from和 size定義的分頁機制依然有內存溢出的可能,而 max_result_ window設置的 10000條則是對 Elastiesearch 的一.種保護機制。
那麼 Elasticsearch 爲何要這麼設計呢?首先,在互聯網時代的數據檢索應該經過類似度算法,提升檢索結果與用戶指望的附和度,而不該該讓用戶在檢索結果中本身挑選滿意的數據。以互聯網搜索爲例,用戶在瀏覽搜索結果時不多會看到第 3頁之後的內容。假如用戶在翻到第 10000 條數據時尚未找到須要的結果,那麼他對這個搜索引擎必定會很是失望。
_source 參數
元字段_source 中存儲了文檔的原始數據。若是請求中沒有指定_source,Elasticsearch 默認返回整個_ source,或者若是_ source沒有存儲,那麼就只返回匹配文檔的元數據:_ id、_type、_index 和_score。
例如:
get kibana_sample_data_flights/_search
{
"query":{
"match_all":{}
},
"_source":["OriginCountry","DestCountry"]
}
你不只能夠返回字段列表,還能夠指定通配符。例如,若是想同時返回"
DestCountry "和" DestWeather "字段,能夠這樣配置_ source: "Dest*"。也能夠使用通配字符串的數組來指定多個通配符,例如_ source:[" Origin*", "* Weather "]。
get kibana_sample_data_flights/_search
{
"query":{
"match_all":{}
},
"_source":["Origin*","*Weather"]
}
不只能夠指定哪些字段須要返回,還能夠指定哪些字段無須返回。好比:get kibana_sample_data_flights/_search
{
"_source":{
"includes":["*.lon","*.lat"],
"excludes":"DestLocation.*"
}
}
排序
大多搜索最後涉及的元素都是結果的排序( sort )。若是沒有指定 sort 排序選項,Elasticsearch返回匹配的文檔的時候,按照_ score 取值的降序來排列,這樣最爲相關的(得分最高的)文檔就會排名在前。爲了對字段進行升序或降序排列,
指定映射的數組,而不是字段的數組。經過在 sort 中指定字段列表或者是字段映射,能夠在任意數量的字段上進行排序。
例如:
get kibana_sample_data_flights/_search
{
"from":100,
"size":20,
"query":{
"match_all":{}
},
"_source":["Origin*","*Weather"],
"sort":[{"DistanceKilometers":"asc"},{"FlightNum":"desc"}]
}