在 Elasticsearch 中,每一個字段的全部數據都是默認被索引的。html
大多數實體和對象均可以被序列化爲包含鍵值對的JSON對象,JSON對象能表示字符串、數字、布爾值、甚至另外一個對象。以下所示:web
{
"name": "John Smith",
"age": 42,
"confirmed": true,
"join_date": "2014-06-01",
"home": {
"lat": 51.5,
"lon": 0.1
},
"accounts": [
{
"type": "facebook",
"id": "johnsmith"
},
{
"type": "twitter",
"id": "johnsmith"
}
]
}
複製代碼
文檔的定義:它是指最頂層或者根對象, 這個根對象被序列化成 JSON 並存儲到 Elasticsearch 中,指定了惟一 ID。數據庫
元數據 —— 有關文檔的信息,與文檔包含的數據相區分。json
有以下三個元數據:數組
_index:文檔存放在哪網絡
一個索引應該是因共同的特性被分組到一塊兒的文檔集合,如可能存儲全部的產品在索引 products
中。索引名必須小寫,不能如下劃線開頭,不能包含逗號。併發
_type:文檔的類型elasticsearch
Elasticsearch 公開了一個稱爲 types (類型)的特性,它容許您在索引中對數據進行邏輯分區。不一樣 types 的文檔可能有不一樣的字段,但最好可以很是類似。至關於在_index下繼續細分。ide
_id:文檔的惟一標識post
ID 是一個字符串, 當它和 _index
以及 _type
組合就能夠惟一肯定 Elasticsearch 中的一個文檔。
如何肯定一個文檔的位置呢?就如上面所說的,三個元數據肯定一個文檔。如儲存一個文檔:
PUT /{index}/{type}/{id}
{
"field": "value",
...
}
複製代碼
如何像數據庫自增主鍵那樣由ElasticSearch提供id呢,使用POST謂詞就能夠了。
POST /website/blog/
{
"title": "My second blog entry",
"text": "Still trying this out...",
"date": "2014/01/01"
}
複製代碼
會自動生成一個基於 Base64 編碼且長度爲 20 個字符的 GUID 字符串
一樣的只須要把謂詞改成GET,同時提供三個元數據就能夠了:
GET /website/blog/123?pretty
複製代碼
加上pretty參數使得 JSON 響應體更加可讀。若是隻想返回文檔的一部分則在url上添加_source指定想要的字段就好了。
在 Elasticsearch 中文檔是不可改變的,不能修改它們,只能進行替換。至關於使用PUT再從新將整個文檔PUT一下,Elasticsearch將舊文檔標記爲已刪除,並增長一個全新的文檔。
(建立和刪除文檔略)
使用 update
API能夠部分更新文檔,例如在某個請求時對計數器進行累加。對象被合併到一塊兒,覆蓋現有的字段,增長新的字段。如:
POST /website/blog/1/_update
{
"doc" : {
"tags" : [ "testing" ],
"views": 0
}
}
複製代碼
在文檔中增長了tags和views字段。
也可使用腳本和參數更新:
POST /website/blog/1/_update
{
"script" : "ctx._source.tags+=new_tag",
"params" : {
"new_tag" : "search"
}
}
複製代碼
爲了不數據丟失, update
API 在檢索步驟時檢索獲得文檔當前的 _version
號,並傳遞版本號到重建索引步驟的 index
請求。 若是另外一個進程修改了處於檢索和從新索引步驟之間的文檔,那麼 _version
號將不匹配,更新請求將會失敗。
還能夠在url後加上retry_on_conflict=5
參數,表示失敗以前重試5次。
ElasticSearch使用樂觀併發控制,每一個文檔都有一個版本號_version,當文檔被修改時版本號遞增。 Elasticsearch 使用這個 _version
號來確保變動以正確順序獲得執行。咱們經過指定想要修改文檔的 version
號來達到這個目的,若是該版本不是當前版本號,咱們的請求將會失敗(也就是一次Compare And Set)。
使用mget API來取回多個文檔能夠減小網絡流量,參數在請求體裏的docs數組中提供:
GET /_mget
{
"docs" : [
{
"_index" : "website",
"_type" : "blog",
"_id" : 2
},
{
"_index" : "website",
"_type" : "pageviews",
"_id" : 1,
"_source": "views"
}
]
}
複製代碼
還有其餘的批量查詢方法能夠查看官方文檔。
返回文檔順序和請求的一致。
很簡單一看就懂,使用bulk API,主要就是語法的問題,不太好掌握。
POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "My first blog post" }
{ "index": { "_index": "website", "_type": "blog" }}
{ "title": "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} }
複製代碼
什麼條件也不附加的空搜索,搜索ElasticSearch中的全部文檔:
GET /_search
複製代碼
返回全部查詢結果的前十個文檔而不是隻是返回id。
前面的空搜索是搜索全部文檔,若是要想指定元數據搜索怎麼辦呢?很好辦,在url中指明便可:
/gb/_search
在 gb
索引中搜索全部的類型
/gb,us/_search
在 gb
和 us
索引中搜索全部的文檔
/g*,u*/_search
在任何以 g
或者 u
開頭的索引中搜索全部的類型
/gb/user/_search
在 gb
索引中搜索 user
類型
/gb,us/user,tweet/_search
在 gb
和 us
索引中搜索 user
和 tweet
類型
/_all/user,tweet/_search
在全部的索引中搜索 user
和 tweet
類型
和傳統的數據庫同樣,ElasticSearch也有分頁的功能,使用from
和 size
參數:
size
顯示應該返回的結果數量,默認是 10
from
顯示應該跳過的初始結果數量,默認是 0
GET /_search?size=5&from=10
複製代碼
以前咱們看到的搜索都是有個JSON請求體,可是還有一種更簡便的輕量級搜索方式.
搜索全部包含關鍵字的文檔:
GET /_search?q=mary
複製代碼
搜索包含關鍵字的全部文檔:
GET /_search?q=mary
複製代碼
指定匹配多個關鍵字的文檔:
GET /_search?q=+name:john +tweet:mary
複製代碼
+
前綴表示必須與查詢條件匹配。相似地, -
前綴表示必定不與查詢條件匹配。
注意+、-、:都要使用URL編碼,實際上上面的查詢語句應該是:
GET /_search?q=%2Bname%3Ajohn+%2Btweet%3Amary
複製代碼
那麼ElasticSearch如何從JSON的不一樣字段搜索關鍵字呢?原來ElasticSearch在儲存一個文檔上,會將該JSON全部字段提取出來拼接成一個字符串,而後增長一個_all字段,將該字符串添加到all字段上。
請求體查詢就像是一個帶請求體的GET請求:
GET /_search
{
"from": 30,
"size": 10
}
複製代碼
Elasticsearch 使用查詢表達式能夠以簡單的 JSON 接口來編寫查詢語句。只須要將語句傳遞給query參數就能夠了。如查詢 tweet
字段中包含 elasticsearch
的 tweet:
GET /_search
{
"query": {
"match": {
"tweet": "elasticsearch"
}
}
}
複製代碼
當你有多個查詢條件是能夠合併查詢語句:
{
"bool": {
"must": { "match": { "tweet": "elasticsearch" }},
"must_not": { "match": { "name": "mary" }},
"should": { "match": { "tweet": "full text" }},
"filter": { "range": { "age" : { "gt" : 30 }} }
}
}
複製代碼
match_all
匹配全部文檔:{ "match_all": {}}
複製代碼
{ "match": { "age": 26 }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}
複製代碼
match
查詢:{
"multi_match": {
"query": "full text search",
"fields": [ "title", "body" ]
}
}
複製代碼
{
"range": {
"age": {
"gte": 20,
"lt": 30
}
}
}
複製代碼
{ "term": { "age": 26 }}
{ "term": { "date": "2014-09-01" }}
{ "term": { "public": true }}
{ "term": { "tag": "full_text" }}
複製代碼
若是想在多個字段上查詢多種多樣的文本怎麼辦呢?可使用bool
查詢來實現你的需求。bool
查詢接收如下參數:
must
文檔 必須 匹配這些條件才能被包含進來。
must_not
文檔 必須不 匹配這些條件才能被包含進來。
should
若是知足這些語句中的任意語句,將增長 _score
,不然,無任何影響。它們主要用於修正每一個文檔的相關性得分。
filter
必須 匹配,但它以不評分、過濾模式來進行。這些語句對評分沒有貢獻,只是根據過濾標準來排除或包含文檔。
以下面這個查詢的意思是必須知足title
字段匹配 how to make millions
而且不被標識爲 spam
的文檔。若是是starred且在2014年後的郵件會有更高的排名:
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }},
{ "range": { "date": { "gte": "2014-01-01" }}}
]
}
複製代碼
每個子查詢都獨自地計算文檔的相關性得分。一旦他們的得分被計算出來, bool
查詢就將這些得分進行合併而且返回一個表明整個布爾操做的得分。
bool查詢默認是評分的,將 bool
查詢包裹在 filter
語句中,就能夠在過濾標準中增長布爾邏輯。