简介
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,是强制更新,这会导致主分片和副本分片数据不一致的情况。
注意:本文归作者所有,未经作者允许,不得转载