来自于 ElasticSearch 参考的 Getting started 章节
ES如何处理数据
ES 中 主要的数据容器被称为 index,index 可以类比为 传统SQL领域中的 一个数据库 ,在索引中,数据按照 数据的类型进行分类,在 ES 中这被称为 映射(mapping),一个映射描述了 记录是如何组成的 (被称为 字段(field));
保存在 ES 中的每条记录 必须是 一个 JSON 对象。
ES 内部是一个 无模式(schema-less)数据存储,当向ES 中提交数据(put),在插入数据的过程中处理记录,首先将 记录拆分成字段(field),然后更新 schema 来管理被插入的数据。
为了管理大量的记录,ES 使用常用的方法将 索引(index)拆分成许多 分片(shard),这样就可以将这些分片分散到多个节点。
每条记录 仅仅保存在一个 分片中,在处理记录的时候就不会干涉到其他的 分区;
ES 内部有一套严格的规则来保证 在 index/mapping/records 上操作的安全性;在 ES 中,操作被分为以下以下几种:
集群操作:在集群级别,所有的写数据都需要被锁定,首先,应用到 主节点,然后应用到 次级节点。 读操作
索引管理操作:
记录操作:
1. 更新文档
ES 提供几乎实时的 数据操作 和 搜索能力 ,预期有一秒钟的延迟 。
★ 索引 / 替换文档
假定现在索引如下的 文档
PUT /customer/external/1?pretty -d
{
"name": "xiaoming"
}
响应如下 :
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 1,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"created": true
}
接着 ,我又索引了如下除了 json 不同其他都相同的文档
PUT /customer/external/1?pretty -d
{
"name": "zhangsan"
}
响应如下 :
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 2,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"created": false
}
此时查询 ID 为 1 的 文档 :
GET /customer/external/1?pertty -d
响应 :
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 2,
"found": true,
"_source": {
"name": "zhangsan"
}
}
我们可以发现 ,版本号发生了改变 ,而且第二次的并不是新创建的 。 ES 会 将 ID 为 1 的顶部已经存在的一个文档 替换 (即重新索引)为一个新的文档。
我们在索引一个文档时,ID 是可选的 ,如果 没有指定 ID ,则 ES 会 随机产生一个 ID 来索引该文档 ,但是 此时必须使用 POST 提交 :
POST /customer/external?pretty -d
{
"name" : "lisi"
}
响应如下 :
{
"_index": "customer",
"_type": "external",
"_id": "AVbEw2-DBbPWabWvhAyq",
"_version": 1,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"created": true
}
补充 : GET POST DELETE 区别 (引用地址 :Using HTTP Methods for RESTful Services)
HTTP Verb | CRUD | Entire Collection (e.g. /customers) | Specific Item (e.g. /customers/{id}) |
---|---|---|---|
POST | Create | 201 (Created), 'Location' header with link to /customers/{id} containing new ID. | 404 (Not Found), 409 (Conflict) if resource already exists.. |
GET | Read | 200 (OK), list of customers. Use pagination, sorting and filtering to navigate big lists. | 200 (OK), single customer. 404 (Not Found), if ID not found or invalid. |
PUT | Update/Replace | 404 (Not Found), unless you want to update/replace every resource in the entire collection. | 200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid. |
PATCH | Update/Modify | 404 (Not Found), unless you want to modify the collection itself. | 200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid. |
DELETE | Delete | 404 (Not Found), unless you want to delete the whole collection—not often desirable. | 200 (OK). 404 (Not Found), if ID not found or invalid. |
2. 更新文档
需要注意的是 ES 在内部并不是真正执行了更新的操作 ,真正的操作是 : ES 会删除 旧的 文档 ,然后立刻索引一个新的文档 ,这里也要使用 POST,并且暂时每次只能更新一个单一的文档
更新之前 ID 为 1 的 文档 :
POST /customer/external/1/_update?pretty -d
{
"doc":{"name" : "wangwu"}
}
响应 :
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 3,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
}
}
可以发现版本从之前 的 2 变成了 3.
3. 删除 文档
使用 DELETE :
DELETE /customer/external/1?pretty -d
4. 批处理
使用 _bulk API ,如果其中一个动作失败,仍然会执 行下一个动作,最后每个动作都会返回执行的状态 :200 代表执行成功
同时 索引两个文档
POST /customer/external/_bulk?pretty -d
{ "index" :{"_id" : "1"}}
{ "name" : "chenliu"}
{ "index" :{"_id" : "2"}}
{ "name" : "shunliu"}
如下响应 :
{
"took": 251,
"errors": false,
"items": [
{
"index": {
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 1,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"status": 201
}
},
{
"index": {
"_index": "customer",
"_type": "external",
"_id": "2",
"_version": 1,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"status": 201
}
}
]
}
更新和删除同时请求:
POST /customer/external/_bulk?pretty -d
{"update" : {"_id":"1"}}
{"doc":{"name":"xiaohong"}}
{"delete":{"_id":"2"}}