elasticsearch 文檔操作接口

INDEX API

示例:

PUT /test/user/1
{
  "name": "silence",
  "age": 27
}

說明:
1.索引文檔使用PUT方法,需要指定index(test)、type(user)和文檔編號(hào),提交數(shù)據(jù)為json格式為文檔的內(nèi)容
2.在索引文檔時(shí),會(huì)自動(dòng)檢查index和type是否存在,若不存在則自動(dòng)創(chuàng)建,對(duì)于type會(huì)自動(dòng)調(diào)用putmapping方法為type自動(dòng)創(chuàng)建mapping,當(dāng)提交的json數(shù)據(jù)新增字段時(shí)也會(huì)自動(dòng)對(duì)type自動(dòng)調(diào)用putmapping方法在mapping中添加新的字段類型
可通過elasticsearch.yml中添加配置禁用自動(dòng)創(chuàng)建index和type

action.auto_create_index: false        #禁用自動(dòng)創(chuàng)建index
index.mapper.dynamic: false            #禁用自動(dòng)生成type

在某些時(shí)候允許某類型或者禁用某類型的index自動(dòng)創(chuàng)建,則可以使用匹配模式和黑白名單形式進(jìn)行配置

action.auto_create_index: +test*,+temp*,+tmp*       #只允許自動(dòng)創(chuàng)建以test,temp,tmp開頭的index

說明: 若action.auto_create_index設(shè)置為true或允許某些index執(zhí)行, index.mapper.dynamic設(shè)置為false, 則可第一次時(shí)index自動(dòng)創(chuàng)建一個(gè)type,后續(xù)不能再單獨(dú)創(chuàng)建新的type

3.文檔中的version屬性
es為每個(gè)文檔自動(dòng)設(shè)置一個(gè)version屬性, version從1開始, 當(dāng)文檔發(fā)生更新,刪除操作時(shí)version都會(huì)自增1, version是范圍為[1, 9.2e+18]的整數(shù), 在獲取或查詢文檔是version作為文檔的一部分返回
version屬性主要使用樂觀鎖機(jī)保證數(shù)據(jù)在讀取后再進(jìn)行更新動(dòng)作時(shí)的數(shù)據(jù)一致性問題,在提交請(qǐng)求時(shí)通過指定version參數(shù)表示存儲(chǔ)的版本必須符合條件時(shí)才可執(zhí)行成功, 默認(rèn)條件為兩者一致,若不提交version表示不進(jìn)行檢查
使用方法:
例如編號(hào)為1的文檔version為7

{
   "_index": "test",
   "_type": "user",
   "_id": "1",
   "_version": 7,
   "found": true,
   "_source": {
      "name": "silence",
      "age": 27
   }
}

當(dāng)我們使用如下請(qǐng)求執(zhí)行更新動(dòng)作可看到執(zhí)行成功,并且version自增1, 返回結(jié)果中為8:
輸入:

PUT /test/user/1?version=7
{
  "name": "silence",
  "age": 28
}

輸出:

{
   "_index": "test",
   "_type": "user",
   "_id": "1",
   "_version": 8,
   "created": false
}

當(dāng)我們?cè)俅伟l(fā)出version=7的請(qǐng)求得到的響應(yīng)為:

{
   "error": "VersionConflictEngineException[[test][2] [user][1]: version conflict, current [8], provided [7]]",
   "status": 409
}
version_type值 說明
internal 默認(rèn)值, 表示指定version必須與存儲(chǔ)中的version一致, 若成功則存儲(chǔ)version自增1
external/external_gt 指定值必須大于存儲(chǔ)中的version, 若成功存儲(chǔ)version設(shè)置為提交的version
external_gte 指定值必須大于等于存儲(chǔ)中的version, 若成功存儲(chǔ)version設(shè)置為提交的version
force 強(qiáng)制更新,并將存儲(chǔ)version設(shè)置為提交的version

可自己測(cè)試version>8的請(qǐng)求依然失敗, 此時(shí)你可能會(huì)想到在高并發(fā)情況下此種效率是否會(huì)低效, 可能你會(huì)在內(nèi)存中放置一個(gè)version+1的副本, 通過內(nèi)存中對(duì)副本進(jìn)行自增, 然后異步方式提高并發(fā), 此時(shí)執(zhí)行成功率會(huì)下降并且導(dǎo)致數(shù)據(jù)丟失, 在此種情況下只要滿足你指定的version大于存儲(chǔ)中的版本號(hào)即可, 為解決此種問題es提供version_type可以指定使用的比較策略:

version_type值 說明
internal 默認(rèn)值, 表示指定version必須與存儲(chǔ)中的version一致, 若成功則存儲(chǔ)version自增1
external/external_gt 指定值必須大于存儲(chǔ)中的version, 若成功存儲(chǔ)version設(shè)置為提交的version
external_gte 指定值必須大于等于存儲(chǔ)中的version, 若成功存儲(chǔ)version設(shè)置為提交的version
force 強(qiáng)制更新,并將存儲(chǔ)version設(shè)置為提交的version

4.op_type: 在提交請(qǐng)求時(shí)指定op_type=create, 表示若id不存在時(shí)創(chuàng)建, 否則失敗
輸入

PUT /test/user/1?op_type=create
{
  "name": "silence",
  "age": 28
}

輸出:

{
   "error": "DocumentAlreadyExistsException[[test][2] [user][1]: document already exists]",
   "status": 409
}

op_type=create的另一種表示方法為:

PUT /test/user/1/_create
{
  "name": "silence",
  "age": 28
}

5.ID生成器: 在大多數(shù)情況下我們不需要維護(hù)也不關(guān)心文檔的id是什么, 在es中可以為文檔自動(dòng)生成id,方式為使用post方式提交參數(shù), 并在請(qǐng)求中不指定id值(若指定則使用指定的id值)
6.routing路由分配: 在創(chuàng)建index時(shí)通常會(huì)將index數(shù)據(jù)存放在不同的shard上,es默認(rèn)通過hash(id) % shard_num決定將文檔存儲(chǔ)在哪個(gè)shard上,此刻你應(yīng)該想到routing的作用,對(duì),就是用來指定做負(fù)載是hash的輸入?yún)?shù):
輸入:

POST /test/user/?routing=name
{
  "name": "silence",
  "age": 28
}

若在索引文檔時(shí)顯示指定routing,則在提交文檔中必須存在指定routing對(duì)應(yīng)的值,否則執(zhí)行失敗

7.分布式執(zhí)行
索引操作會(huì)被路由到shard上,并在包含該shard的node中執(zhí)行,若存在復(fù)制shard,則當(dāng)所有復(fù)制節(jié)點(diǎn)從主shard中執(zhí)行成功后,返回結(jié)果

8.一致性
為防止某些網(wǎng)絡(luò)節(jié)點(diǎn)錯(cuò)誤,默認(rèn)情況下當(dāng)索引成功數(shù)量>=仲裁(replicas/2+1)時(shí),則認(rèn)為操作成功,對(duì)于復(fù)制數(shù)量為1時(shí)則數(shù)據(jù)一共存兩份(主shard和復(fù)制shard),此時(shí)若主shard寫成功則認(rèn)為執(zhí)行成功
可在elasticsearch.yml中將action.write_consistency設(shè)置為one,all,quorum修改判斷依據(jù)

9.刷新shard
為了在索引文檔成功后立即查詢到文檔(當(dāng)shard刷新后才可search到), 可以通過設(shè)置refresh=true在索引文檔成功后立即執(zhí)行存儲(chǔ)該數(shù)據(jù)shard的刷新動(dòng)作, 在設(shè)置前應(yīng)該對(duì)索引和查詢進(jìn)行對(duì)性能測(cè)試,對(duì)于get接口獲取文檔是完全實(shí)時(shí)的

再次分享自己趟過的一個(gè)坑:
背景:需要在一堆日志中統(tǒng)計(jì)所有存在的源IP,日志時(shí)按天存放的,代碼結(jié)構(gòu)如下:

def get_all_store_hosts():
   '''
      返回es中存儲(chǔ)中所有ip
      在索引doc時(shí)未設(shè)置refresh
   '''
   return _all_

def get_distinct_hosts_from_logs(day):
   '''
      從日志中查詢所有的ip并去重
   '''
   return _hosts_

def store_hosts(hosts)
   '''
   將新的ip存儲(chǔ)到es中
   '''

def stat(day):
   _all_ = get_all_store_hosts()
   _hosts_ = get_distinct_hosts_from_logs:
   _hosts_ = [_host for _host in  _hosts_ if _host not in _all_]
   if len(_hosts_):
      store_hosts(_hosts_)

if __name__ == '__main__':
   for day in xrange(1, 30):
      stat(day)

各位看著有問題嗎?好吧,貌似沒有問題,但是呢執(zhí)行完成后,你會(huì)驚奇的發(fā)現(xiàn)es中你的統(tǒng)計(jì)的數(shù)據(jù)里面存儲(chǔ)大量重復(fù)的ip,問題原因大家已經(jīng)知道了吧

解決方法:我在內(nèi)存中做了一個(gè)緩存,通過緩存去重,當(dāng)在緩存中不存在時(shí)則放入緩存中并存儲(chǔ)到es

  1. timeout
    當(dāng)文檔被索引時(shí)會(huì)從主shard將數(shù)據(jù)復(fù)制到復(fù)制shard, 主shard需要等待復(fù)制shard的響應(yīng)后返回執(zhí)行結(jié)果, 此等待時(shí)間默認(rèn)為1min, 可以通過在請(qǐng)求中添加timeout修改此時(shí)間

GET API

示例:
輸入:
GET /test/user/1
輸入:

{
   "_index": "test",
   "_type": "user",
   "_id": "1",
   "_version": 3,
   "found": true,
   "_source": {
      "name": "silence",
      "age": 28,
      "book": {
         "name": "迷失的自己"
      }
   }
}

說明:
1.可以通過GET方法根據(jù)文檔的ID讀取文檔內(nèi)容
_index,_type,_id三元組唯一標(biāo)識(shí)一個(gè)文檔, 分別表示索引,類型和文檔id
_version為文檔的版本
found表示是否查詢到結(jié)果, true表示存在, false表示不存在
_source是真正的文檔內(nèi)容

2.可以通過HEAD方法根據(jù)reponse header信息判斷文檔是否存在
輸入:curl -XHEAD -i "http://localhost:9200/test/user/1"

HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 0`

輸入:curl -XHEAD -i "http://localhost:9200/test/user/1
輸出:

HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=UTF-8
Content-Length: 0

可以看到若文檔存在使用HEAD方法則返回狀態(tài)碼為200,否則狀態(tài)碼為404

3.GET操作默認(rèn)是實(shí)時(shí)的,也就是說文檔索引后可立即讀取,并不像Search需要等待shard刷新,但是通過在GET請(qǐng)求中通過參數(shù)realtime=false或者在elasticsearch.yml配置action.get.realtime:false禁用
4.在GET數(shù)據(jù)時(shí)可以使用"_all"替代要查詢的_type, 此時(shí)會(huì)返回在所有type中第一個(gè)匹配到的document
5.在GET數(shù)據(jù)時(shí)可以通過_source, _source_include & _source_exclude設(shè)置返回文檔包含的屬性
輸入: GET /test/user/1?_source=false 不返回任何_source內(nèi)容
輸入: GET /test/user/1?_source=name 只返回_source中的name
輸入: GET /test/user/1?_source_include=*.name&_source_exclude=name

_source常用于需要返回一兩個(gè)字段的情況, 內(nèi)容較多的文檔屬性值進(jìn)行篩選時(shí)可以組合_source_include和_source_exclude
6.若只想返回_source中的內(nèi)容可以使用:GET /test/user/1/_source
7.若在索引文檔時(shí)指定了routing_key為了可以正確GET到文檔,則需要在GET請(qǐng)求中添加routing指定正確的routing_key
8.默認(rèn)GET文檔執(zhí)行在復(fù)制shard的上,但可以通過設(shè)置preference為_primary或者_(dá)local, _primary表示在主shard上執(zhí)行, _local表示在一個(gè)分配且可用的shard上執(zhí)行
9.GET請(qǐng)求中也可以添加refresh=true參數(shù)強(qiáng)制使獲取文檔相關(guān)shard刷新, 從而可以被search到
10.在GET請(qǐng)求發(fā)出后,會(huì)根據(jù)需要獲取文檔id將請(qǐng)求轉(zhuǎn)發(fā)到一個(gè)相關(guān)的復(fù)制節(jié)點(diǎn)上執(zhí)行并返回結(jié)果
11.可以在GET請(qǐng)求中指定version屬性用于需要獲取符合規(guī)則version的文檔

DELETE API

示例:
輸入
DELETE /test/user/1

說明:
1.在DELETE方法提交的參數(shù)中可以設(shè)置version屬性用于刪除符合規(guī)則的version文檔
2.當(dāng)在index文檔是設(shè)置routing_key, 那么在刪除文檔時(shí)也需要使用routing設(shè)置正確的routing_key
3.當(dāng)刪除文檔是若index不存在, 則es會(huì)自動(dòng)創(chuàng)建
4.刪除文檔請(qǐng)求會(huì)被轉(zhuǎn)發(fā)到主shard上, 主shard操作完成后, 各復(fù)制shard會(huì)從主shard進(jìn)行同步

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,948評(píng)論 18 139
  • Neil Zhu,簡(jiǎn)書ID Not_GOD,University AI 創(chuàng)始人 & Chief Scientist...
    朱小虎XiaohuZhu閱讀 2,021評(píng)論 0 5
  • 介紹 elasticsearch是一個(gè)高效的、可擴(kuò)展的全文搜索引擎 基本概念 Near Realtime(NRT)...
    imsilence閱讀 791評(píng)論 0 0
  • 最近幾天,一個(gè)付費(fèi)問答系統(tǒng)“分答”火了。我很開心,于是也跟著湊熱鬧,昨晚花了十幾塊錢去問一位暢銷書作家:我的公眾號(hào)...
    草蒙茸閱讀 401評(píng)論 0 0
  • 飛黃騰達(dá),不知道是褒義詞還是貶義詞,很多人說的是財(cái)運(yùn),也有極少數(shù)人說的是夢(mèng)想開花結(jié)果,關(guān)于這個(gè)詞的解釋我不是很清楚...
    芊芊好好閱讀 396評(píng)論 0 0