elasticsearch文檔索引API(一)

上篇文章向讀者介紹了Elasticsearch中文檔的基本讀寫操作流程,以及分片、副本等的工作流程,本文我們來看看Elasticsearch文檔索引API。

本文是Elasticsearch系列的第八篇,閱讀前面的文章,有助於更好的理解本文:



索引API

在索引中添加或者更新JSON文檔,前面斷斷續續介紹了過幾次,相信小夥伴們都有所瞭解,這裏再來複習下,例如在twitter索引的 _doctype中添加一個一個id爲1的文檔,如下:

curl -X PUT "localhost:9200/twitter/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'

執行結果如下:

在執行結果中, _shards字段提供了索引操作的複製過程的詳細信息:

  • total:表示應執行索引操作的分片(主分片和副本分片)的數量
  • successful:表示索引操作成功的分片數
  • failed:返回一個數組,這個數組是在副本分片上索引操作失敗的情況下相關錯誤的數組

在索引操作成功的情況下,successful至少爲1。

注意

當創建索引操作成功時,副本的分片有可能還沒啓動(默認情況下,只有主分片纔是必須的,但是這個行爲是可以修改的)。此時,返回的total將等於基於numberofreplicas設置的所有分片數,而successful則等於已成功的分片數(主分片+副本分片),如果沒有失敗的分片,failed將會爲0。

自動創建索引

在上面的案例中,我們向twitter索引庫中添加了一個文檔,在文檔添加之前,twitter索引庫是不存在的,但是並不會影響文檔的添加,因爲在創建索引文檔時,如果索引庫不存在,es會自動創建索引庫,並且自動爲特定類型創建動態類型映射(關於Mapping我們在後文會向大家詳細介紹)。

可以通過在elasticsearch.yml配置文件中將action.autocreateindex設置爲false來禁用自動創建索引庫,也可以通過將index.mapper.dynamic設置爲false來禁用自動映射創建。這是來自官網的介紹,但是在實際操作中,如果這樣配置會拋出如下異常信息:

java.lang.IllegalArgumentException: the [action.auto_create_index] setting value [false] is too restrictive. disable [action.auto_create_index] or set it to [.watches, .triggered_watches, .watcher-history-*]

從這個意思可以看出,這是說直接這樣配置限制性太強了,因此不可以這樣配置,應該禁用該屬性,或者採用黑白名單列表,例如,設置action.autocreateindex 爲 +aaa,-bbb,+ccc,-( +表示允許,-表示不允許,這裏表示以aaa或者ccc開始index可以自動創建,以bbb或者其他字符開始的index不可以自動創建)。例如,在elasticsearch.yml中添加如下配置:

action.auto_create_index: .monitoring-kibana*,.monitoring-data*,.watches,.kibana,.watcher-history*,.monitoring-es*,.security,.triggered_watches,aaa,-bbb,+ccc*,-ddd*

這個配置表示對於名稱爲bbb的索引,以及名稱以ddd開頭的索引不會自動創建,除了這兩類,其他枚舉出來的索引名稱都會自動創建,而未枚舉出來的名稱則不會自動創建,例如想自動創建一個名爲fff的索引,發現創建不了,如下:

以ddd開頭的索引名稱也無法自動創建:

而以ccc開頭的索引名稱則可以自動創建出來,如下:

對於無法自動創建的索引,可以先手動創建index,然後再添加文檔。

版本控制

版本控制實際上涉及到Elasticsearch的併發訪問問題。小夥伴們應該知道,數據庫鎖有悲觀鎖和樂觀鎖之分:

  • 悲觀鎖,顧名思義就是很悲觀,每次操作數據時都認爲數據也會被其他線程修改,因此屏蔽一切有可能破壞數據完整性的操作,在傳統的關係型數據庫中,常見的行鎖、表鎖、讀/寫鎖都用到了這種鎖機制。
  • 樂觀鎖,顧名思義就是很樂觀,認爲每一次的數據操作都不會發生併發訪問衝突,因此不會鎖定要操作的數據資源,只是在每次提交時檢查操作是否違反了數據完整性,Elasticsearch中就是採用了這種鎖機制,使用樂觀鎖的一個好處是可以提高系統的吞吐量。

Elasticsearch作爲一個分佈式系統,在elasticsearch文檔讀寫模型一文中,我們已經向讀者介紹了Elasticsearch的讀/寫模型,讀者已經瞭解到,一個操作在主分片執行完成後,會被轉發到其他副本分片上去執行,這個過程是一個併發操作,也是一個異步操作,既然是異步操作,就有可能發生順序問題,例如一個最新的更新文檔先到達副本上,而另一個本該先到達的更新文檔反而後到達了,此時就會破壞數據完整性,解決這個問題,可以使用Elasticsearch中提供的版本控制功能。

執行如下命令添加一個文檔:

curl -X PUT "localhost:9200/twitter/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'

執行結果如下:

可以看到,新創建的文檔版本號爲1,此時,我們再執行一個更新操作,去修改user的值,如下:

curl -X POST "localhost:9200/twitter/_doc/1/_update?pretty" -H 'Content-Type: application/json' -d'
{
    "script" : "ctx._source.user=\"sang\""
}
'

執行結果如下:

可以看到,user已經成功更新了,此時版本號也變爲2了。此時如果再想去獲取或者更新version爲1的文檔,則會發生版本衝突問題,如果要指定版本號,版本號必須和當前版本號一致:

也可以使用外部版本號,使用外部版本號的話,要求外部版本號大於等於當前版本號,如下:

curl -X POST "localhost:9200/twitter/_doc/1?pretty&version=3&version_type=external" -H 'Content-Type: application/json' -d'
{
    "name" : "sang2"
}
'

執行完後,外部版本號會作爲新的版本號。

注意 版本控制是完全實時的,並且不受搜索操作的NRT的影響。如果未提供版本,則執行該操作而不進行任何版本檢查。

操作類型

有兩種方式可以明確指定索引操作類型,實現一種“put-if-absent”行爲,不過這種操作只有在目標文檔不存在的情況下有效,如果目標文檔已經存在,則操作失敗(如果不加該參數,不會出現操作失敗的情況,只是verison會發生變化)。

有如下兩種指定操作類型的方式:

curl -X PUT "localhost:9200/twitter/_doc/1?op_type=create" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'

另一種是:

curl -X PUT "localhost:9200/twitter/_doc/1/_create" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'

好了,本文就先介紹到這裏,有問題歡迎留言討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章