【Elasticsearch7.0】文档接口之index接口

star2017 1年前 ⋅ 594 阅读

简介

index接口对指定的索引添加或者修改json文档,确保他可以被搜索,下面示例表示新增id为1的数据:

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

返回值:

{
  "_index" : "test",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 3
}

_shards头文件提供了索引操作复制过程的信息:
total:表示有多少分片副本(主分片和副本分片)应该执行索引操作。
successful:表示执行索引操作成功的分片数量。
failed:表示在执行索引操作时失败的分片数量。
如果成功的索引操作至少为1,则索引操作成功。
注意:当一个索引返回成功时,那么不会查询副本分片(默认情况下,只需要主节点,但是可以更改此行为),一般情况下total等于number_of_replicas设置的数量,successful等于执行的分片数量(主分片+副本分片),如果他们执行没有错误,那么failed为0。

自动索引创建

如果执行index接口的时候,该索引不存在,那么会自动去创建一个索引,而且会使用默认配置的索引模板。如果映射不存在的话,也会创建一个自定义映射,默认情况下,新的属性和对象将自动被创建到映射中。注:关于映射的相关知识后面会讲到。
自动索引创建是通过action.auto_create_index来控制的,该设置默认是true,意味着总是可以自动创建索引,自动创建索引也是有要求的,必须要匹配某些模式的索引才能创建,多个索引可以用逗号隔开,它还可以通过在列表中使用+或-前缀模式显式地允许和禁止,可以设置为false来完全禁止它。

curl -XPUT "http://127.0.0.1:9200/_cluster/settings?pretty" -H "Content-Type: application/json" -d'
{
    "persistent": {
        "action.auto_create_index": "twitter,index10,-index1*,+ind*,-myIndex" 
    }
}'

表示接收twitter,index10,ind开头的,不支持index1,myIndex开头的索引名称。默认为true。
例如之前的例子,修改下索引名称,在执行

curl -XPUT "http://127.0.0.1:9200/myIndex/_doc/1?pretty" -H "Content-Type: application/json" -d'

返回值:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "index_not_found_exception",
        "reason" : "no such index [myIndex] and [action.auto_create_index] contains [-myIndex] which forbids automatic creation of the index",
        "index_uuid" : "_na_",
        "index" : "myIndex"
      }
    ],
    "type" : "index_not_found_exception",
    "reason" : "no such index [myIndex] and [action.auto_create_index] contains [-myIndex] which forbids automatic creation of the index",
    "index_uuid" : "_na_",
    "index" : "myIndex"
  },
  "status" : 404
}

如上所示,就会报错了。

操作类型

index操作可以接收op_type参数,可以设置为create,表示强制进行创建文档,如果数据不存在那么会去创建,当设置为create,如果数据已经存在那么不会进行创建,看下面的示例:

curl -XPUT "http://127.0.0.1:9200/test/_doc/1?pretty&op_type=create" -H "Content-Type: application/json" -d'
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}'

返回值:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "version_conflict_engine_exception",
        "reason" : "[1]: version conflict, document already exists (current version [2])",
        "index_uuid" : "sNvURoEgQX-a2VLHwJt59Q",
        "shard" : "0",
        "index" : "test"
      }
    ],
    "type" : "version_conflict_engine_exception",
    "reason" : "[1]: version conflict, document already exists (current version [2])",
    "index_uuid" : "sNvURoEgQX-a2VLHwJt59Q",
    "shard" : "0",
    "index" : "test"
  },
  "status" : 409
}

因为之前已经创建过了,所以再次执行就会报错。换个其他的id,就可以执行成功。
也可以使用另外一个语法来代替op_type参数:

curl -XPUT "http://127.0.0.1:9200/test/_create/3?pretty" -H "Content-Type: application/json" -d'
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}'

返回值:

{
  "_index" : "test",
  "_type" : "_doc",
  "_id" : "3",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 3,
  "_primary_term" : 4
}

自动id生成

index操作可以不指定id,来看个示例:

curl -XPOST "http://127.0.0.1:9200/test/_doc?pretty" -H "Content-Type: application/json" -d'
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}'

返回值:

{
  "_index" : "test",
  "_type" : "_doc",
  "_id" : "Rp7ijGsBwQd3nJ0NAzC6",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 4,
  "_primary_term" : 4
}

这里会自动生成id,如"_id" : "Rp7ijGsBwQd3nJ0NAzC6",op_type默认为create,注意:这里使用POST。

乐观并发控制

index操作可以指定if_seq_no和if_primary_term两个参数,他们是用来控制你要修改的文档是不是最新的,如果值不匹配,那么进行更新失败,会返回VersionConflictException异常,并且返回状态为409。

路由

默认情况下,文档在分片的位置是根据id来进行hash的,当然也可以明确的指定具体根据哪个值进行路由,可以通过routing参数来设置,例如:

curl -XPOST "http://127.0.0.1:9200/test/_doc?pretty&routing=kimchy" -H "Content-Type: application/json" -d'
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}'

返回值为:

{
  "_index" : "test",
  "_type" : "_doc",
  "_id" : "R55PjWsBwQd3nJ0NCzBv",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 5,
  "_primary_term" : 4
}

在上面的例子中,“_doc”文档根据提供的路由参数“kimchy”路由到一个分片。在设置显式映射时,可以选择使用_routing字段来指导索引操作,以从文档本身提取路由值,这是以额外的文档解析传递(非常小)的代价实现的,如果定义了_routing映射并将其设置为必需的,那么如果没有提供,index操作将失败。

分布式

index操作根据路由定位到主分片,在该主分片的节点上执行操作,如果主分片完成了操作,那么他会把操作转发给其他可以用的副本。

等待活跃分片

为了提升系统的写操作,index操作可以设置一定数量的活跃分片,在执行操作之前会等待一段时间,如果不够所需的活跃分片数,那么index操作会等,直到达到所需的活跃分片数,或者执行超时。默认情况下,index操作只要主分片是活跃的就会进行写操作,如:wait_for_active_shards=1,可以通过设置index.write.wait_for_active_shards来设置需要多少活动分片,如果想对某个请求做处理,那么可以使用wait_for_active_shards参数。可以配置正整数或者all(表示number_of_replicas+1),如果指定负数或者大于分片总数那么会进行报错。
例如:一个集群有3个节点,A、B、C,A为主分片,创建索引为index,并设置副本为3,在不修改参数之前,执行index操作,那么只要主分片是活跃的就可以执行操作,这意味着如果B和C都挂了,A还是可以继续处理index操作,但是数据只在一个分片上。如果设置了wait_for_active_shards值为3,index操作需要3个活跃分片才能执行,如果设置为all,那么index操作将不能执行,直到有新的节点加入集群。
该设置可以提高数据写入到所有的副本的几率,但是他也不能完全确保,因为检查是在index操作之前执行的,还是有一定的几率会出问题。有可能会出现其他副本写失败,但是主分片上是写成功的。在index操作的返回值中的_shards参数会体现成功数和失败数。

{
    "_shards" : {
        "total" : 2,
        "failed" : 0,
        "successful" : 2
    }
}

刷新

控制你新增的数据什么时候可以被搜索到。

无更新

使用index操作来更新文档时,总数被创建一个新的文档,即使他已经存在了。也就是说es中默认是没有更新的,如果你不想一直被创建新的文档,那么可以在_update接口中设置detect_noop为true,这个设置在index接口中不可用,因为index接口不会去获取旧的数据,也不会跟之前的数据进行比较。
什么时候应该使用无操作更新?这个需要综合来看,比如数据源发送更新的频率,以及分片更新的时候有多少查询。

超时

在执行index操作的时候,被分配的分片可能不可用,有可能是网络问题,也有可能是机器问题,默认情况下,index操作会等待1分钟,如果1分钟之后还是没有响应,那么就返回失败,timeout参数可以指定等待多少时间,下面的示例表示等待5分钟:

curl -XPUT "http://127.0.0.1:9200/test/_doc/1?timeout=5m&pretty" -H "Content-Type:application/json" -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}'

返回值:

{
  "_index" : "test",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 3,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 6,
  "_primary_term" : 5
}

版本控制

每次文档都会生成一个版本号,默认使用内置的自增版本号,从1开始自增,每次修改、删除、新增都会修改版本号。当然这个版本号可以使用外部的一个值,如维护在数据库里,可以设置version_type为external来开启,这个值必须是数字,必须大于等于0且小于9.2e+18。
当使用外部版本号的时候,系统会检查传入的版本号是否大于当前存储的版本号,如果为true,那么文档将操作成功并生成新的版本号,如果传入的版本号小于或者等于存储的版本号,那么会返回版本冲突的错误,如:

curl -XPUT "http://127.0.0.1:9200/test/_doc/1?version=2&version_type=external&pretty" -H "Content-Type:application/json" -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}'

返回值:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "version_conflict_engine_exception",
        "reason" : "[1]: version conflict, current version [3] is higher or equal to the one provided [2]",
        "index_uuid" : "sNvURoEgQX-a2VLHwJt59Q",
        "shard" : "0",
        "index" : "test"
      }
    ],
    "type" : "version_conflict_engine_exception",
    "reason" : "[1]: version conflict, current version [3] is higher or equal to the one provided [2]",
    "index_uuid" : "sNvURoEgQX-a2VLHwJt59Q",
    "shard" : "0",
    "index" : "test"
  },
  "status" : 409
}

注意:版本控制是实时的,如果没有提供版本,那么上面的操作将进行无版本控制,只有在版本号大于存储版本的时候才能执行成功,
使用外部版本号的一个好处是如果执行异步index操作的时候可以依赖数据库的版本号,只要修改数据库的版本号就可以了。使用外部版本控制使使用索引操作变的简单,因为index操作是无序的,这样只会保存最新的版本号的数据。

版本类型

除了external类型外,es还支持其他的类型,主要有:
1、internal
只有传入的版本号与存储的版本号相同的时候,才可以操作成功。
2、external或者external_gt
只有传入的版本号大于存储的版本号时,才可以操作成功,或者存储的文档不存在,会新建一个文档,并且文档的版本号也是新的,版本号值必须是非负的整数。
3、external_gte
只有传入的版本号大于等于存储的版本号时,才可以操作成功,如果没有文档那么也可以操作成功,会新建一个文档,并且文档的版本号也是新的,版本号值必须是非负的整数。
注意:external_gte版本类型用于特殊的用例,应该谨慎使用,如果使用不当,会导致数据丢失,之前还有一个参数:force,是强制更新,这会导致主分片和副本分片数据不一致的情况。

本文为博主原创文章,未经博主允许不得转载。
更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: