1 .什么是文檔
在 Elasticsearch 中,術語文檔有著特定的含義。它是指最頂層或者根對象, 這個根對象被序列化成 JSON 并存儲到 Elasticsearch 中,指定了唯一 ID。
2.文檔元數據
一個文檔不僅僅包含它的數據,也包含元數據——有關文檔的信息。三個必須的元數據元素如下:
-
_index
文檔在哪存放 -
_type
文檔表示的對象類別 -
_id
文檔唯一標識
其他元數據另做介紹
3. 索引文檔
一個文檔的上面三個元數據唯一標識一個文檔。我們可以自己提供_id
,也可以讓index API自動生成。
PUT /{index}/{type}/{id}
{
"field": "value",
...
}
示例:
PUT /website/blog/123
{
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
返回值:
{
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 1,
"created": true
}
如果沒有提供_id
,Elasticsearch 可以幫我們自動生成 ID 。
POST /website/blog/
{
"title": "My second blog entry",
"text": "Still trying this out...",
"date": "2014/01/01"
}
返回值:
{
"_index": "website",
"_type": "blog",
"_id": "AVFgSgVHUP18jI2wRx0w",
"_version": 1,
"created": true
}
自動生成的 ID 是 URL-safe、 基于 Base64 編碼且長度為20個字符的 GUID 字符串.
4.取回一個文檔
GET /website/blog/123?pretty
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 1,
"found" : true,
"_source" : {
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
}
如果我們請求一個不存在的文檔,我們仍舊會得到一個 JSON 響應體.
curl -i -XGET http://localhost:9200/website/blog/124?pretty
響應:
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=UTF-8
Content-Length: 83
{
"_index" : "website",
"_type" : "blog",
"_id" : "124",
"found" : false
}
3.1 返回文檔的一部分
默認情況下, GET
請求會返回整個文檔,這個文檔正如存儲在_source
字段中的一樣。但是也許你只對其中的title
字段感興趣。單個字段能用_source
參數請求得到,多個字段也能使用逗號分隔的列表來指定。
GET /website/blog/123?_source=title,text
響應:
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 1,
"found" : true,
"_source" : {
"title": "My first blog entry" ,
"text": "Just trying this out..."
}
}
或者,如果你只想得到 _source 字段,不需要任何元數據,你能使用 _source 端點:
GET /website/blog/123/_source
響應:
{
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
4.更新整個文檔
在 Elasticsearch 中文檔是不可改變的,不能修改它們。相反,如果想要更新現有的文檔,需要重建索引或者進行替換,我們可以使用相同的 index
API 進行實現
PUT /website/blog/123
{
"title": "My first blog entry",
"text": "I am starting to get the hang of this...",
"date": "2014/01/02"
}
響應:
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 2,
"created": false
}
在內部,Elasticsearch 已將舊文檔標記為已刪除,并增加一個全新的文檔。盡管你不能再對舊版本的文檔進行訪問,但它并不會立即消失。當繼續索引更多的數據,Elasticsearch 會在后臺清理這些已刪除文檔。
5.創建新文檔
_index
、 _type
和 _id
的組合可以唯一標識一個文檔。所以,確保創建一個新文檔的最簡單辦法是,使用索引請求的POST
形式讓 Elasticsearch 自動生成唯一_id
:
POST /website/blog/
{ ... }
然而,如果已經有自己的 _id ,那么我們必須告訴 Elasticsearch ,只有在相同的 _index 、 _type 和 _id 不存在時才接受我們的索引請求。這里有兩種方式,他們做的實際是相同的事情。使用哪種,取決于哪種使用起來更方便。
PUT /website/blog/123/_create
{ ... }
如果創建新文檔的請求成功執行,Elasticsearch 會返回元數據和一個201 Created
的 HTTP 響應碼。另一方面,如果具有相同的_index
、_type
和_id
的文檔已經存在,Elasticsearch 將會返回409 Conflict
響應碼,以及如下的錯誤信息:
{
"error": {
"root_cause": [
{
"type": "document_already_exists_exception",
"reason": "[blog][123]: document already exists",
"shard": "0",
"index": "website"
}
],
"type": "document_already_exists_exception",
"reason": "[blog][123]: document already exists",
"shard": "0",
"index": "website"
},
"status": 409
}
6.刪除文檔
刪除文檔的語法和我們所知道的規則相同,只是使用DELETE
方法:DELETE /website/blog/123
如果找到該文檔,
{
"found" : true,
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 3
}
如果文檔沒有找到,
{
"found" : false,
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 4
}
7.空搜索
GET /_search
響應
{
"hits" : {
"total" : 14,
"hits" : [
{
"_index": "us",
"_type": "tweet",
"_id": "7",
"_score": 1,
"_source": {
"date": "2014-09-17",
"name": "John Smith",
"tweet": "The Query DSL is really powerful and flexible",
"user_id": 2
}
},
... 9 RESULTS REMOVED ...
],
"max_score" : 1
},
"took" : 4,
"_shards" : {
"failed" : 0,
"successful" : 10,
"total" : 10
},
"timed_out" : false
}
返回結果中最重要的部分是 hits
,它包含total
字段來表示匹配到的文檔總數,并且一個hits
數組包含所查詢結果的前十個文檔。
max_score
值是與查詢所匹配文檔的 _score
的最大值 。took
值 告訴我們執行整個搜索請求耗費了多少毫秒._shards
部分 告訴我們在查詢中參與分片的總數, 以及這些分片成功了多少個失敗了多少個。正常情況下我們不希望分片失敗,但是分片失敗是可能發生的。如果我們遭遇到一種災難級別的故障,在這個故障中丟失了相同分片的原始數據和副本,那么對這個分片將沒有可用副本來對搜索請求作出響應。假若這樣,Elasticsearch 將報告這個分片是失敗的,但是會繼續返回剩余分片的結果。timed_out
值告訴我們查詢是否超時。默認情況下,搜索請求不會超時。 如果低響應時間比完成結果更重要,你可以指定 timeout
為 10 或者 10ms(10毫秒),或者 1s(1秒):
GET /_search?timeout=10ms
應當注意的是 timeout
的節點返回到目前為止收集的結果并且關閉連接。在后臺,其他的分片可能仍在執行查詢即使是結果已經被發送了。使用超時是因為 SLA(服務等級協議)對你是很重要的,而不是因為想去中止長時間運行的查詢。
8多索引,多類型
如果不對某一特殊的索引或者類型做限制,就會搜索集群中的所有文檔。Elasticsearch 轉發搜索請求到每一個主分片或者副本分片,匯集查詢出的前10個結果,并且返回給我們。然而,經常的情況下,你想在一個或多個特殊的索引并且在一個或者多個特殊的類型中進行搜索。我們可以通過在URL中指定特殊的索引和類型達到這種效果,如下所示:
/gb/_search # 在 gb 索引中搜索所有的類型
/g*,u*/_search # 在任何以 g 或者 u 開頭的索引中搜索所有的類型
/gb/user/_search # 在 gb 索引中搜索 user 類型
/_all/user,tweet/_search # 在所有的索引中搜索 user 和 tweet 類型
當在單一的索引下進行搜索的時候,Elasticsearch 轉發請求到索引的每個分片中,可以是主分片也可以是副本分片,然后從每個分片中收集結果。多索引搜索恰好也是用相同的方式工作的--只是會涉及到更多的分片。