Elasticsearch 2.20 文檔篇:更新刪除文檔
來自: http://my.oschina.net/secisland/blog/614513
Elasticsearch的更新文檔API準許通過腳本操作來更新文檔。更新操作從索引中獲取文檔,執行腳本,然后獲得返回結果。它使用版本號來控制文檔獲取或者重建索引。
備注:在Elasticsearch中的更新操作是完全從新索引文件。
我們新建一個文檔:
請求:PUT http://localhost:9200/test/type1/1?pretty
參數:
{ "counter" : 1, "tags" : ["red"] }
腳本開啟功能
在最新版本的Elasticsearch中,基于安全考慮(如果用不到,請保持禁用),默認禁用了動態腳本功能.如果被禁用,在使用腳本的時候則報以下的錯誤:
scripts of
type
[inline], operation [update] and lang [groovy] are disabled
可以用以下方式完全開啟動態腳本功能,在config/elasticsearch.yml文件,在最后添加以下代碼:
script.inline: on
script.indexed: on
script.file: on
配置后,重啟Elasticsearch。
下面我們用腳本來更新此文檔。
請求:POST http://localhost:9200/test/type1/1/_update?pretty
參數:
{ "script" : { "inline": "ctx._source.counter += count", "params" : { "count" : 4 } } }
執行完后,我們在查詢一下文檔內容,可以發現counter的值為5:
{ "_index" : "test", "_type" : "type1", "_id" : "1", "_version" : 5, "found" : true, "_source" : { "counter" : 5, "tags" : [ "red" ] } }
在看下面的更新操作:
請求:POST http://localhost:9200/test/type1/1/_update?pretty
參數:
{ "script" : { "inline": "ctx._source.tags += tag", "params" : { "tag" : "blue" } } }
返回的內容為,表示更新成功,我們看一下_version為6,比剛才的值增加了1:
{ "_index" : "test", "_type" : "type1", "_id" : "1", "_version" : 6, "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 } }
然后我們在查詢一下文檔內容:
{ "_index" : "test", "_type" : "type1", "_id" : "1", "_version" : 6, "found" : true, "_source" : { "counter" : 5, "tags" : [ "red", "blue" ] } }
在腳本中除了_source外其他內置參數也可以使用,例如_index, _type, _id, _version, _routing, _parent, _timestamp, _ttl。
下面我們通過腳本增加一列。
請求:POST http://localhost:9200/test/type1/1/_update?pretty
參數:
{ "script" : "ctx._source.name_of_new_field = \"value_of_new_field\"" }
然后查詢此文檔:
{ "_index" : "test", "_type" : "type1", "_id" : "1", "_version" : 7, "found" : true, "_source" : { "counter" : 5, "tags" : [ "red", "blue" ], "name_of_new_field" : "value_of_new_field" } }
從中可以看出,文檔中又增加了一列。
刪除一列,請求和剛才的一樣,參數變為:
{ "script" : "ctx._source.remove(\"name_of_new_field\")" }
甚至可以通過表達式來判斷做某些事情,例如:下面的示例將刪除的文件如果標簽字段包含藍色,否則什么也不做(空):
請求參數:
{ "script" : { "inline": "ctx._source.tags.contains(tag) ? ctx.op = \"delete\" : ctx.op = \"none\"", "params" : { "tag" : "blue" } } }
部分文檔更新:
該更新接口還支持更新部分文檔,將文檔合并到現有文檔中(簡單的遞歸合并、對象的內部合并、替換核心的“鍵/值”和數組)。例如:
{ "doc" : { "name" : "new_name" } }
更新后,可以發現文檔中多了一列name。
{ "_index" : "test", "_type" : "type1", "_id" : "1", "_version" : 23, "found" : true, "_source" : { "counter" : 5, "tags" : [ "red", "blue" ], "name" : "new_name" } }
當文檔指定的值與現有的_source合并。當新的文檔和老的文檔不一致的時候,文檔將會被從新建立索引。當新舊文檔一樣的時候,則不進行從建索引的操作。可以通過設置detect_noop為false,讓任何情況下都從新建立索引,例如下面的更新操作:
{ "doc" : { "name" : "new_name" }, "detect_noop": false }
刪除文檔
刪除文檔相對比較簡單:
請求:DELETE http://localhost:9200/test/type1/1
返回的內容為:
{ "found": true, "_index": "test", "_type": "type1", "_id": "1", "_version": 24, "_shards": { "total": 2, "successful": 1, "failed": 0 }}
則表示刪除了此文檔。
賽克藍德(secisland)后續會逐步對Elasticsearch的最新版本的各項功能進行分析,近請期待。也歡迎加入secisland公眾號進行關注。