elasticsearch 文档操作接口

INDEX API

示例:

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

说明:
1.索引文档使用PUT方法,需要指定index(test)、type(user)和文档编号,提交数据为json格式为文档的内容
2.在索引文档时,会自动检查index和type是否存在,若不存在则自动创建,对于type会自动调用putmapping方法为type自动创建mapping,当提交的json数据新增字段时也会自动对type自动调用putmapping方法在mapping中添加新的字段类型
可通过elasticsearch.yml中添加配置禁用自动创建index和type

action.auto_create_index: false        #禁用自动创建index
index.mapper.dynamic: false            #禁用自动生成type

在某些时候允许某类型或者禁用某类型的index自动创建,则可以使用匹配模式和黑白名单形式进行配置

action.auto_create_index: +test*,+temp*,+tmp*       #只允许自动创建以test,temp,tmp开头的index

说明: 若action.auto_create_index设置为true或允许某些index执行, index.mapper.dynamic设置为false, 则可第一次时index自动创建一个type,后续不能再单独创建新的type

3.文档中的version属性
es为每个文档自动设置一个version属性, version从1开始, 当文档发生更新,删除操作时version都会自增1, version是范围为[1, 9.2e+18]的整数, 在获取或查询文档是version作为文档的一部分返回
version属性主要使用乐观锁机保证数据在读取后再进行更新动作时的数据一致性问题,在提交请求时通过指定version参数表示存储的版本必须符合条件时才可执行成功, 默认条件为两者一致,若不提交version表示不进行检查
使用方法:
例如编号为1的文档version为7

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

当我们使用如下请求执行更新动作可看到执行成功,并且version自增1, 返回结果中为8:
输入:

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

输出:

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

当我们再次发出version=7的请求得到的响应为:

{
   "error": "VersionConflictEngineException[[test][2] [user][1]: version conflict, current [8], provided [7]]",
   "status": 409
}
version_type值 说明
internal 默认值, 表示指定version必须与存储中的version一致, 若成功则存储version自增1
external/external_gt 指定值必须大于存储中的version, 若成功存储version设置为提交的version
external_gte 指定值必须大于等于存储中的version, 若成功存储version设置为提交的version
force 强制更新,并将存储version设置为提交的version

可自己测试version>8的请求依然失败, 此时你可能会想到在高并发情况下此种效率是否会低效, 可能你会在内存中放置一个version+1的副本, 通过内存中对副本进行自增, 然后异步方式提高并发, 此时执行成功率会下降并且导致数据丢失, 在此种情况下只要满足你指定的version大于存储中的版本号即可, 为解决此种问题es提供version_type可以指定使用的比较策略:

version_type值 说明
internal 默认值, 表示指定version必须与存储中的version一致, 若成功则存储version自增1
external/external_gt 指定值必须大于存储中的version, 若成功存储version设置为提交的version
external_gte 指定值必须大于等于存储中的version, 若成功存储version设置为提交的version
force 强制更新,并将存储version设置为提交的version

4.op_type: 在提交请求时指定op_type=create, 表示若id不存在时创建, 否则失败
输入

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生成器: 在大多数情况下我们不需要维护也不关心文档的id是什么, 在es中可以为文档自动生成id,方式为使用post方式提交参数, 并在请求中不指定id值(若指定则使用指定的id值)
6.routing路由分配: 在创建index时通常会将index数据存放在不同的shard上,es默认通过hash(id) % shard_num决定将文档存储在哪个shard上,此刻你应该想到routing的作用,对,就是用来指定做负载是hash的输入参数:
输入:

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

若在索引文档时显示指定routing,则在提交文档中必须存在指定routing对应的值,否则执行失败

7.分布式执行
索引操作会被路由到shard上,并在包含该shard的node中执行,若存在复制shard,则当所有复制节点从主shard中执行成功后,返回结果

8.一致性
为防止某些网络节点错误,默认情况下当索引成功数量>=仲裁(replicas/2+1)时,则认为操作成功,对于复制数量为1时则数据一共存两份(主shard和复制shard),此时若主shard写成功则认为执行成功
可在elasticsearch.yml中将action.write_consistency设置为one,all,quorum修改判断依据

9.刷新shard
为了在索引文档成功后立即查询到文档(当shard刷新后才可search到), 可以通过设置refresh=true在索引文档成功后立即执行存储该数据shard的刷新动作, 在设置前应该对索引和查询进行对性能测试,对于get接口获取文档是完全实时的

再次分享自己趟过的一个坑:
背景:需要在一堆日志中统计所有存在的源IP,日志时按天存放的,代码结构如下:

def get_all_store_hosts():
   '''
      返回es中存储中所有ip
      在索引doc时未设置refresh
   '''
   return _all_

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

def store_hosts(hosts)
   '''
   将新的ip存储到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)

各位看着有问题吗?好吧,貌似没有问题,但是呢执行完成后,你会惊奇的发现es中你的统计的数据里面存储大量重复的ip,问题原因大家已经知道了吧

解决方法:我在内存中做了一个缓存,通过缓存去重,当在缓存中不存在时则放入缓存中并存储到es

  1. timeout
    当文档被索引时会从主shard将数据复制到复制shard, 主shard需要等待复制shard的响应后返回执行结果, 此等待时间默认为1min, 可以通过在请求中添加timeout修改此时间

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方法根据文档的ID读取文档内容
_index,_type,_id三元组唯一标识一个文档, 分别表示索引,类型和文档id
_version为文档的版本
found表示是否查询到结果, true表示存在, false表示不存在
_source是真正的文档内容

2.可以通过HEAD方法根据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方法则返回状态码为200,否则状态码为404

3.GET操作默认是实时的,也就是说文档索引后可立即读取,并不像Search需要等待shard刷新,但是通过在GET请求中通过参数realtime=false或者在elasticsearch.yml配置action.get.realtime:false禁用
4.在GET数据时可以使用"_all"替代要查询的_type, 此时会返回在所有type中第一个匹配到的document
5.在GET数据时可以通过_source, _source_include & _source_exclude设置返回文档包含的属性
输入: GET /test/user/1?_source=false 不返回任何_source内容
输入: GET /test/user/1?_source=name 只返回_source中的name
输入: GET /test/user/1?_source_include=*.name&_source_exclude=name

_source常用于需要返回一两个字段的情况, 内容较多的文档属性值进行筛选时可以组合_source_include和_source_exclude
6.若只想返回_source中的内容可以使用:GET /test/user/1/_source
7.若在索引文档时指定了routing_key为了可以正确GET到文档,则需要在GET请求中添加routing指定正确的routing_key
8.默认GET文档执行在复制shard的上,但可以通过设置preference为_primary或者_local, _primary表示在主shard上执行, _local表示在一个分配且可用的shard上执行
9.GET请求中也可以添加refresh=true参数强制使获取文档相关shard刷新, 从而可以被search到
10.在GET请求发出后,会根据需要获取文档id将请求转发到一个相关的复制节点上执行并返回结果
11.可以在GET请求中指定version属性用于需要获取符合规则version的文档

DELETE API

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

说明:
1.在DELETE方法提交的参数中可以设置version属性用于删除符合规则的version文档
2.当在index文档是设置routing_key, 那么在删除文档时也需要使用routing设置正确的routing_key
3.当删除文档是若index不存在, 则es会自动创建
4.删除文档请求会被转发到主shard上, 主shard操作完成后, 各复制shard会从主shard进行同步

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,494评论 18 139
  • Neil Zhu,简书ID Not_GOD,University AI 创始人 & Chief Scientist...
    朱小虎XiaohuZhu阅读 1,996评论 0 5
  • 介绍 elasticsearch是一个高效的、可扩展的全文搜索引擎 基本概念 Near Realtime(NRT)...
    imsilence阅读 770评论 0 0
  • 最近几天,一个付费问答系统“分答”火了。我很开心,于是也跟着凑热闹,昨晚花了十几块钱去问一位畅销书作家:我的公众号...
    草蒙茸阅读 382评论 0 0
  • 飞黄腾达,不知道是褒义词还是贬义词,很多人说的是财运,也有极少数人说的是梦想开花结果,关于这个词的解释我不是很清楚...
    芊芊好好阅读 356评论 0 0