程序中大多的實體或對象能夠被序列化為包含鍵值對的JSON對象,鍵(key)是字段(field)或屬性(property)的名字,值(value)可以是字符串、數字、波爾類型、另一個對象、值數組或者其他特殊類型,比如表示日期的字符串或者表示地理位置的對象。
文檔元數據(Document MetaData):
一個文檔不只有數據。它還包含了元數據(metadata)——關於文檔的信息。三個必須的元數據節點是:
節點 | 說明 |
---|---|
_index |
文檔存儲的地方 |
_type |
文檔代表的對象的類 |
_id |
文檔的唯一標識 |
_index
索引(index)類似於關系型數據庫里的“數據庫”——它是我們存儲和索引關聯數據的地方。
事實上,我們的數據被存儲和索引在分片(shards)中,索引只是一個把一個或多個分片分組在一起的邏輯空間。然而,這只是一些內部細節——我們的程序完全不用關心分片。對於我們的程序而言,文檔存儲在索引(index)中。剩下的細節由Elasticsearch關心既可。
后面會繼續探討如何創建並管理索引,但現在,我們將讓Elasticsearch為我們創建索引。我們唯一需要做的僅僅是選擇一個索引名。這個名字必須是全部小寫,不能以下划線開頭,不能包含逗號。讓我們使用website
做為索引名。
_type
在應用中,我們使用對象表示一些“事物”,例如一個用戶、一篇博客、一個評論,或者一封郵件。每個對象都屬於一個類(class),這個類定義了屬性或與對象關聯的數據。user
類的對象可能包含姓名、性別、年齡和Email地址。
在關系型數據庫中,我們經常將相同類的對象存儲在一個表里,因為它們有着相同的結構。同理,在Elasticsearch中,我們使用相同類型(type)的文檔表示相同的“事物”,因為他們的數據結構也是相同的。
每個類型(type)都有自己的映射(mapping)或者結構定義,就像傳統數據庫表中的列一樣。所有類型下的文檔被存儲在同一個索引下,但是類型的映射(mapping)會告訴Elasticsearch不同的文檔如何被索引。 我們將會在《映射》章節探討如何定義和管理映射,但是現在我們將依賴ELasticsearch去自動處理數據結構。
_type
的名字可以是大寫或小寫,不能包含下划線或逗號。我們將使用blog
做為類型名。
_id
id僅僅是一個字符串,它與_index
和_type
組合時,就可以在ELasticsearch中唯一標識一個文檔。當創建一個文檔,你可以自定義_id
,也可以讓Elasticsearch幫你自動生成。
ps:還有其它部分其它元數據,后續再介紹。
使用自己的ID
如果你的文檔有自然的標識符(例如user_account
字段或者其他值表示文檔),你就可以提供自己的_id
,使用這種形式的index
API:
PUT /{index}/{type}/{id}
{"key": "value"...}
如,PUT /website/blog/123
{
"title": "My blog entry",
"text": "漢語你可以。。 ",
"date": "2015/07/16"
}
{
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 5,
"created": false
}
Elasticsearch中每個文檔都有版本號,每當文檔變化(包括刪除)都會使_version
增加。后續我們將探討如何使用_version
號確保你程序的一部分不會覆蓋掉另一部分所做的更改。
自增ID
如果我們的數據沒有自然ID,我們可以讓Elasticsearch自動為我們生成。請求結構發生了變化:PUT
方法——“在這個URL中存儲文檔”
變成了POST
方法——"在這個文檔下存儲文檔"
。(注:原來是把文檔存儲到某個ID對應的空間,現在是把這個文檔添加到某個_type
下)。
URL現在只包含_index
和_type
兩個字段:
POST /website/blog/
{
"title": "My second blog entry", "text": "Still trying this out...", "date": "2015/07/16" }
響應內容與剛才類似,只有_id
字段變成了自動生成的值:
{
"_index": "website", "_type": "blog", "_id": "AU6Vi9GsUzILmCnC2hkX", "_version": 1, "created": true }
更新整個文檔
文檔在Elasticsearch中是不可變的——我們不能修改他們。如果需要更新已存在的文檔,我們可以使用《索引文檔》提到的index
API 重建索引(reindex) 或者替換掉它。
PUT /website/blog/123 { "title": "My first blog entry", "text": "I am starting to get the hang of this...", "date": "2014/01/02" }
在響應中,我們可以看到Elasticsearch把_version
增加了。
{
"_index" : "website", "_type" : "blog", "_id" : "123", "_version" : 2, "created": false <1> }
- <1>
created
標識為false
因為同索引、同類型下已經存在同ID的文檔。
在內部,Elasticsearch已經標記舊文檔為刪除並添加了一個完整的新文檔。舊版本文檔不會立即消失,但你也不能去訪問它。Elasticsearch會在你繼續索引更多數據時清理被刪除的文檔。
在后面探討update
API,這個API 似乎 允許你修改文檔的局部,但事實上Elasticsearch遵循與之前所說完全相同的過程,這個過程如下:
- 從舊文檔中檢索JSON
- 修改它
- 刪除舊文檔
- 索引新文檔
唯一的不同是update
API完成這一過程只需要一個客戶端請求既可,不再需要get
和index
請求了。
刪除文檔
刪除文檔的語法模式與之前基本一致,只不過要使用DELETE
方法:
DELETE /website/blog/1234
如果文檔被找到,Elasticsearch將返回200 OK
狀態碼和以下響應體。注意_version
數字已經增加了。
{
"found" : true, "_index" : "website", "_type" : "blog", "_id" : "1234", "_version" : 3 }
如果文檔未找到,我們將得到一個404 Not Found
狀態碼,響應體是這樣的:
{
"found" : false, "_index" : "website", "_type" : "blog", "_id" : "1234", "_version" : 4 }
盡管文檔不存在——"found"的值是false——_version依舊增加了。這是內部記錄的一部分,它確保在多節點間不同操作可以有正確的順序。刪除一個文檔也不會立即從磁盤上移除,它只是被標記成已刪除。Elasticsearch將會在你之后添加更多索引的時候才會在后台進行刪除內容的清理。