elasticsearch文档索引API(一)
上篇文章向读者介绍了Elasticsearch中文档的基本读写操作流程,以及分片、副本等的工作流程,本文我们来看看Elasticsearch文档索引API。
本文是Elasticsearch系列的第八篇,阅读前面的文章,有助于更好的理解本文:
1.elasticsearch安装与配置
2.初识elasticsearch中的REST接口
3.elasticsearch修改数据
4.elasticsearch文档操作
5.elasticsearch API约定(一)
6.elasticsearch API约定(二)
7.elasticsearch文档读写模型
索引API
在索引中添加或者更新JSON文档,前面断断续续介绍了过几次,相信小伙伴们都有所了解,这里再来复习下,例如在twitter索引的 _doc
type中添加一个一个id为1的文档,如下:
curl -X PUT "localhost:9200/twitter/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
'
执行结果如下:
在执行结果中, _shards
字段提供了索引操作的复制过程的详细信息:
total:表示应执行索引操作的分片(主分片和副本分片)的数量
successful:表示索引操作成功的分片数
failed:返回一个数组,这个数组是在副本分片上索引操作失败的情况下相关错误的数组
在索引操作成功的情况下,successful至少为1。
注意
当创建索引操作成功时,副本的分片有可能还没启动(默认情况下,只有主分片才是必须的,但是这个行为是可以修改的)。此时,返回的total将等于基于numberofreplicas设置的所有分片数,而successful则等于已成功的分片数(主分片+副本分片),如果没有失败的分片,failed将会为0。
自动创建索引
在上面的案例中,我们向twitter索引库中添加了一个文档,在文档添加之前,twitter索引库是不存在的,但是并不会影响文档的添加,因为在创建索引文档时,如果索引库不存在,es会自动创建索引库,并且自动为特定类型创建动态类型映射(关于Mapping我们在后文会向大家详细介绍)。
可以通过在elasticsearch.yml配置文件中将action.autocreateindex设置为false来禁用自动创建索引库,也可以通过将index.mapper.dynamic设置为false来禁用自动映射创建。这是来自官网的介绍,但是在实际操作中,如果这样配置会抛出如下异常信息:
java.lang.IllegalArgumentException: the [action.auto_create_index] setting value [false] is too restrictive. disable [action.auto_create_index] or set it to [.watches, .triggered_watches, .watcher-history-*]
从这个意思可以看出,这是说直接这样配置限制性太强了,因此不可以这样配置,应该禁用该属性,或者采用黑白名单列表,例如,设置action.autocreateindex 为 +aaa,-bbb,+ccc,-( +表示允许,-表示不允许,这里表示以aaa或者ccc开始index可以自动创建,以bbb或者其他字符开始的index不可以自动创建)。例如,在elasticsearch.yml中添加如下配置:
action.auto_create_index: .monitoring-kibana*,.monitoring-data*,.watches,.kibana,.watcher-history*,.monitoring-es*,.security,.triggered_watches,aaa,-bbb,+ccc*,-ddd*
这个配置表示对于名称为bbb的索引,以及名称以ddd开头的索引不会自动创建,除了这两类,其他枚举出来的索引名称都会自动创建,而未枚举出来的名称则不会自动创建,例如想自动创建一个名为fff的索引,发现创建不了,如下:
以ddd开头的索引名称也无法自动创建:
而以ccc开头的索引名称则可以自动创建出来,如下:
对于无法自动创建的索引,可以先手动创建index,然后再添加文档。
版本控制
版本控制实际上涉及到Elasticsearch的并发访问问题。小伙伴们应该知道,数据库锁有悲观锁和乐观锁之分:
悲观锁,顾名思义就是很悲观,每次操作数据时都认为数据也会被其他线程修改,因此屏蔽一切有可能破坏数据完整性的操作,在传统的关系型数据库中,常见的行锁、表锁、读/写锁都用到了这种锁机制。
乐观锁,顾名思义就是很乐观,认为每一次的数据操作都不会发生并发访问冲突,因此不会锁定要操作的数据资源,只是在每次提交时检查操作是否违反了数据完整性,Elasticsearch中就是采用了这种锁机制,使用乐观锁的一个好处是可以提高系统的吞吐量。
Elasticsearch作为一个分布式系统,在elasticsearch文档读写模型一文中,我们已经向读者介绍了Elasticsearch的读/写模型,读者已经了解到,一个操作在主分片执行完成后,会被转发到其他副本分片上去执行,这个过程是一个并发操作,也是一个异步操作,既然是异步操作,就有可能发生顺序问题,例如一个最新的更新文档先到达副本上,而另一个本该先到达的更新文档反而后到达了,此时就会破坏数据完整性,解决这个问题,可以使用Elasticsearch中提供的版本控制功能。
执行如下命令添加一个文档:
curl -X PUT "localhost:9200/twitter/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
'
执行结果如下:
可以看到,新创建的文档版本号为1,此时,我们再执行一个更新操作,去修改user的值,如下:
curl -X POST "localhost:9200/twitter/_doc/1/_update?pretty" -H 'Content-Type: application/json' -d'
{
"script" : "ctx._source.user=\"sang\""
}
'
执行结果如下:
可以看到,user已经成功更新了,此时版本号也变为2了。此时如果再想去获取或者更新version为1的文档,则会发生版本冲突问题,如果要指定版本号,版本号必须和当前版本号一致:
也可以使用外部版本号,使用外部版本号的话,要求外部版本号大于等于当前版本号,如下:
curl -X POST "localhost:9200/twitter/_doc/1?pretty&version=3&version_type=external" -H 'Content-Type: application/json' -d'
{
"name" : "sang2"
}
'
执行完后,外部版本号会作为新的版本号。
注意
版本控制是完全实时的,并且不受搜索操作的NRT的影响。如果未提供版本,则执行该操作而不进行任何版本检查。
操作类型
有两种方式可以明确指定索引操作类型,实现一种“put-if-absent”行为,不过这种操作只有在目标文档不存在的情况下有效,如果目标文档已经存在,则操作失败(如果不加该参数,不会出现操作失败的情况,只是verison会发生变化)。
有如下两种指定操作类型的方式:
curl -X PUT "localhost:9200/twitter/_doc/1?op_type=create" -H 'Content-Type: application/json' -d'
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
'
另一种是:
curl -X PUT "localhost:9200/twitter/_doc/1/_create" -H 'Content-Type: application/json' -d'
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
'
好了,本文就先介绍到这里,有问题欢迎留言讨论。