新增文档是把一条新的文档增加到索引中,使之能够进行搜索,文档的格式是JSON格式。 注意:在Elasticsearch中如果文档的id存在,则更新此文档。例如我们在索引secilog中下面增加一条文档:
请求:PUT http://localhost:9200/secilog/log/1
参数:
{ "collect_type" : "syslog", "collect_date" : "2016-01-11T09:32:12", "message" : "Failed password for root from 192.168.21.1 port 50790 ssh2" }
返回结果:
{ "_index": "secilog", "_type": "log", "_id": "1", "_version": 1, "_shards": { "total": 2, "successful": 1, "failed": 0 }, "created": true }
返回结果中的_shards说明,_shards提供了索引创建的过程信息:
total:文档被创建的时候,在多少个分片中进行了操作,包括主分片和副本分片;
successful:成功建立索引分片的数量,当创建成功后,成功创建索引分片的数量最少是1;
failed:失败建立索引分片的数量。
当创建文档的时候,如果索引不存在,则会自动创建该索引。自动创建的索引会自动映射每个字段的类型。自动创建字段类型是非常灵活的,新的字段类型将会自动匹配字段对象的类型。比如字符串类型,日期类型。自动创建索引可以通过配置文件设置action.auto_create_index为false在所有节点的配置文件中禁用。自动映射的字段类型可以通过配置文件设置index.mapper.dynamic为false禁用。自动创建索引可以通过模板设置索引名称,例如:可以设置 action.auto_create_index为 +aaa*,-bbb*,+ccc*,-* (+表示准许,-表示禁止)。
每个文档都有一个版本号,版本号的具体值放在在创建索引的返回值中("_version":)。通过版本号参数可以达到乐观并发控制的效果。当在操作文档的过程中指定版本号,如果和版本号不一致的时候操作会被拒绝。版本号常用在对事务的处理中。例如,更新刚才创建的文档:
请求:PUT http://localhost:9200/secilog/log/1?version=2&pretty
参数:
{ "message" : "elasticsearch now has versioning support!" }
返回内容为更新失败:
{ "error" : { "root_cause" : [ { "type" : "version_conflict_engine_exception", "reason" : "[log][1]: version conflict, current [-1], provided [2]", "index" : "secilog", "shard" : "2" } ], "type" : "version_conflict_engine_exception", "reason" : "[log][1]: version conflict, current [-1], provided [2]", "index" : "secilog", "shard" : "2" }, "status" : 409 }
注意:版本号是实时更新的,不会存在缓存现象。当操作的时候不指定版本号,则系统不会对版本号是否一致进行检查。
默认情况下对文档的操作版本号从1开始递增,包括修改文档和删除文档。当然版本号还可以从外部获取,比如从数据库中获取,要启用此功能,version_type应设置为external,这个值必须是一个大于0小于 9.2e+18的数字。当使用外部版本号来代替自动生成的版本号时,在操作文档的时候,系统通过对比参数中的版本号是否大于文档中的版本号来做判断,当参数中的版本号大于系统中的版本号,则执行此操作,并更新版本号。反之则拒绝操作(包括小于或者等于)。
版本号同时产生了一个比较实用的功能,只要版本号从源数据库中使用,在异步索引操作的时候就不需要对源数据库的变化执行严格排序。任何操作都只会对最新的版本号起作用,不管这个版本号是内部的还是从外部获取的。
本文由赛克蓝德(secisland)原创,转载请标明作者和出处。
系统同时支持通过op_type=create参数强制命令只执行创建操作,只有系统中不存在此文档的时候才会创建成功。如果不指定此操作类型,如果存在此文档,则会更新此文档。例如再次创建文档:
请求:PUT http://localhost:9200/secilog/log/1?op_type=create&pretty
参数:
{ "collect_type" : "syslog", "collect_date" : "2016-01-11T09:32:12", "message" : "Failed password for root from 192.168.21.2 port 50790 ssh2" }
返回值,表示创建失败:
{ "error" : { "root_cause" : [ { "type" : "document_already_exists_exception", "reason" : "[log][1]: document already exists", "index" : "secilog", "shard" : "3" } ], "type" : "document_already_exists_exception", "reason" : "[log][1]: document already exists", "index" : "secilog", "shard" : "3" }, "status" : 409 }
当不指定op_type=create时候,则更新此文档。
创建操作的另一个写法为:http://localhost:9200/secilog/log/1/_create?pretty
当创建文档的时候,如果不指定id,系统会自动创建id。自动生成的id是一个不会重复的随机数。例如:
请求:POST http://localhost:9200/secilog/log/?op_type=create&pretty
参数:
{ "collect_type" : "syslog", "collect_date" : "2016-01-11T09:32:12", "message" : "Failed password for root from 192.168.21.2 port 50790 ssh2" }
返回值:
{ "_index" : "secilog", "_type" : "log", "_id" : "AVLOV99W6rG7Qqt6i_gk", "_version" : 1, "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "created" : true }
从中可以看出_id自动生成了一个随机数。
默认情况下,分片的选择是通过ID的散列值进行控制,分片的选择。这个只可以通过router 参数进行手动的控制。可以在每个操作的基础上直接通过哈希函数的值来指定分片的选择。例如:
请求:POST http://localhost:9200/secilog/log/?routing=secisland&pretty
在上面的例子中,分片的选择是通过指定routing=secisland参数的哈希值来确定的。
分布式:索引操作主要是针对主节点的分片进行,当主节点完成索引操作后,如果有副本节点,则分发到副本中。
一致性:为了防止当网络出现问题的时候写入不一致,系统只有在有效节点的数量大于一定数量的时候生效(总结点数/2+1),该值可以通过action.write_consistency参数进行修改。
刷新:更新的时候可以指定refresh 参数为true来立即刷新所有的副本,当refresh设置为true的时候,系统做了充分的优化,不会对系统产生任何影响,需要注意的是查询操作refresh参数没有任何的意义。
空操作:当文档内容没有任何改变的时候,更新文档操作也会生效,具体体现在版本号会发生变化。如果不希望此情况发生,在更新的时候指定 detect_noop为true。这个参数在创建索引的时候无效。
超时:默认情况下系统的超时时间是一分钟。可以通过设置timeout来修改超时的时间,例如timeout=5m,表示超时的时间是5分钟。
赛克蓝德(secisland)后续会逐步对Elasticsearch的最新版本的各项功能进行分析,近请期待。也欢迎加入secisland公众号进行关注。