目录shell
说在前面: 本文的全部演示, 都是基于Elasticsearch 6.6.10进行的, 不一样的版本可能存在API发生修改、不支持的状况, 还请注意.json
(1) 适用情景:安全
从其余系统中导入数据到ES时, 会采起这种方式: 使用原有系统中数据已有的惟一标识, 做为ES中document的id.bash
而若是数据一辈子产出来就存储到了ES中, 通常是不适合手动指定id的.服务器
(2) 使用语法:并发
put index/type/id
(3) 使用示例:分布式
PUT employee/developer/1 { "name": "shoufeng", "e_id": 5220 }
(4) 添加成功后的响应信息:ui
{ "_index" : "employee", "_type" : "developer", "_id" : "1", // 指定了id, 控制底层的_id元字段 "_version" : 1, // 当前版本号, 基于此字段进行并发控制 "result" : "created", "_shards" : { "total" : 2, // 参与建立的分片数, 包括Primary和Replica "successful" : 1, // 成功建立索引的分片数量 "failed" : 0 // 建立索引失败的分片数量 }, "_seq_no" : 0, "_primary_term" : 1 }
(1) 使用情景:编码
ES做为数据存储服务器, 应用程序中的数据直接对接到ES中, 这种场景适合自动生成id.code
在多节点并发生成大量数据的场景下, 自动生成id更具安全性.
(2) 使用语法:
POST index/type
(3) 使用示例:
POST employee/developer { "name": "shoufeng", "sex": "male", "age": 20 }
(4) 添加成功后的响应结果:
{ "_index" : "employee", "_type" : "developer", "_id" : "vMxcFWoBfKUnm9s_Uxen", // 没有指定id, 就会自动生成id, 长度为20个字符 "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 0, "_primary_term" : 1 }
官方文档中指出:
Elasticsearch自动生成的id, 长度为20个字符, 是URL安全的, 它是Base64编码的GUID字符串, 多节点(分布式系统)并行生成id时不会发生冲突.
查询时能够不指定type, 即下述的developer, 而用_all代替.
// 查询语法: GET employee/developer/1 // 结果以下: { "_index" : "employee", "_type" : "developer", "_id" : "1", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true, "_source" : { // 文档的元数据 "name" : "shoufeng", "e_id" : 5220 } }
(1) 只获取指定id的文档的_source
内容:
GET employee/developer/1/_source // 结果是: { "name" : "shoufeng", "e_id" : 5220 }
(2) 禁用指定id的文档的_source
字段:
GET employee/developer/1?_source=false // 结果是: { "_index" : "employee", "_type" : "developer", "_id" : "1", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true }
(3) 过滤_source
中的某些field:
// _source_includes和_source_excludes能够匹配通配符* GET employee/developer/1?_source_includes=name,age&_source_excludes=sex GET employee/developer/_search?_source_includes=name,age&_source_excludes=sex
(4) 经过stored_fields
API过滤文档中已存储的字段:
在Elasticsearch 6.0以后, 再也不支持
fields
, 须要使用stored_fields
API替换.
GET employee/developer/1?stored_fields=name,age // 指定id GET employee/developer/_search?stored_fields=name,age // 不指定id, 将查询全部文档
其余查询操做, 将在后续的文章中专门记录.
全量替换是基于指定文档id的修改:
// 语法与建立语法相同: PUT employee/developer/1 { "name": "shoufeng001", // 修改姓名 "age": 20, // 添加年龄 "sex": "male", // 添加性别 "e_id": 5220 }
操做过程说明:
① 若是指定的document id不存在, 就是建立操做;
② 若是指定的document id已经存在, 就是全量替换操做 —— 替换旧文档的JSON串内容;
③ Lucene中倒排索引一旦被建立就是不可变的, 要修改文档内容, 能够采起全量替换的方式 —— 对文档从新创建索引, 替换旧文档的全部内容;
④ ES会将旧文档标记为deleted, 而后根据咱们提交的请求建立一个新文档, 当标记为deleted的文档数达到必定量时, ES会在自动删除这些旧文档.
(1) 存在这样的场景:
咱们不知道索引中是否已经存在某个文档 —— 可能有其余用户在并发添加文档;
为了防止建立操做被执行为全量替换操做, 从而致使数据的丢失, 咱们可使用强制建立的方式, 来避免这种失误.
(2) 强制建立示例:
PUT employee/developer/1?op_type=create { "name": "shoufeng", "age": 20 } // 或者使用: PUT employee/developer/1/_create { "name": "shoufeng", "age": 20 } // 响应结果中出现冲突: { "error": { "root_cause": [ { // 因为文档已经存在, 发生版本冲突, 致使建立失败 "type": "version_conflict_engine_exception", "reason": "[developer][1]: version conflict, document already exists (current version [2])", "index_uuid": "OYu6J2x_S2S5v-R74aq6NQ", "shard": "3", "index": "employee" } ], "type": "version_conflict_engine_exception", "reason": "[developer][1]: version conflict, document already exists (current version [2])", "index_uuid": "OYu6J2x_S2S5v-R74aq6NQ", "shard": "3", "index": "employee" }, "status": 409 }
出现冲突的缘由:
① Elasticsearch经过乐观锁控制每一个文档的
_version
信息, 强制建立语法会对当前操做的文档的_version
信息进行初始化;② 添加索引时, 发现已经存在对应id的文档, 并且其版本号与正在强制建立的文档的版本信息不匹配, 因此报错.
出现冲突后, 咱们就能知道索引中已存在该文档了, 就能够根据本身的应用需求, 采起更改id后从新添加, 或者更改已有的文档等操做.
(1) 删除语法:
DELETE index/type/id
(2) 删除示例:
DELETE employee/developer/1 // 再次查看id为1的文档, 发现"found": false
(3) Elasticsearch删除文档采起的是懒删除机制:
不会当即物理删除, 而是将其标记为deleted, 当被删除的文档数量达到必定级别后, ES会在后台自动删除这些文档.
版权声明
做者: 马瘦风
出处: 博客园 马瘦风的博客
您的支持是对博主的极大鼓励, 感谢您的阅读.
本文版权归博主全部, 欢迎转载, 但请保留此段声明, 并在文章页面明显位置给出原文连接, 不然博主保留追究相关人员法律责任的权利.