0.本文部分内容(数据)总结自 es 开发文档, Document APIs | Elasticsearch Guide [7.2] | Elastic ;
1.本文的es版本是7.2.1;
2.elasticsearch 是一个数据存储,检索和分析引擎;本文介绍的是 es数据存储开发方式;
3.文档存储包括文档保存,修改,删除;(文档查询的开发方式比较复杂,单独新开一篇阐述)
保存文档可以用put请求或post请求;
1) 在customer索引下的 external类型下保存2号文档,文档id设置为2;
Put localhost:9200/customer/external/2
{
"name":"zhangsan2"
}
{
"_index": "customer",
"_type": "external",
"_id": "2",
"_version": 1,
"result": "created", // 这里表示创建
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 2,
"_primary_term": 1
}
2)再执行一次,result就是更新 updated 的了;
{
"_index": "customer",
"_type": "external",
"_id": "2",
"_version": 2,
"result": "updated", // 第2次执行就是更新
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 3,
"_primary_term": 1
}
1) 在customer索引下的 external类型下保存文档(不带文档id);
Post localhost:9200/customer/external
{
"name":"zhangsan_post_1"
}
{
"_index": "customer",
"_type": "external",
"_id": "Qb1Gq4MBJc7j47GNcnTa", // 自动生成id,请求路径不需要设置id
"_version": 1,
"result": "created", // 新增数据
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 4,
"_primary_term": 1
}
【Post请求小结】
2)post请求保存文档,带文档id
Post localhost:9200/customer/external/Qr1Jq4MBJc7j47GNp3RF
{
"name":"zhangsan_post_3"
}
{
"_index": "customer",
"_type": "external",
"_id": "Qr1Jq4MBJc7j47GNp3RF",
"_version": 5, // 版本号递增
"result": "updated", // 更新
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 9,
"_primary_term": 1
}
为了方便验证es文档保存,修改,删除的效果,本文介绍了一个简单查询。
Get localhost:9200/customer/external/1
{}
{
"_index": "customer", // 在哪个索引
"_type": "external", // 在哪个类型
"_id": "1", // 记录id
"_version": 2, // 表明数据被更新过,因为新建数据的版本号是1
"_seq_no": 1, // 并发控制字段,每次更新就会+1;用来做乐观锁;
"_primary_term": 1, // 同上,主分片重新分配,如重启,就会变化
"found": true, //
"_source": { // 真正的内容
"name": "zhangsan"
}
}
步骤1)查询id等于1的文档
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 4,
"_seq_no": 11,
"_primary_term": 1,
"found": true,
"_source": {
"name": "zhangsan2_update_seq_11"
}
}
步骤2)把 seq_no 和 primary_term 作为更新条件
客户端1:(修改成功)
Post localhost:9200/customer/external/1?if_seq_no=11&if_primary_term=1
{
"name":"zhangsan_post_update_c1"
}
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 5,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 12,
"_primary_term": 1
}
客户端2(修改失败),因为 seq_no 因客户端1修改文档的事件而递增了,即不等于11 :
Post localhost:9200/customer/external/1?if_seq_no=11&if_primary_term=1
{
"name":"zhangsan_post_update_c2"
}
{
"error": {
"root_cause": [
{
"type": "version_conflict_engine_exception",
"reason": "[1]: version conflict, required seqNo [11], primary term [1]. current document has seqNo [12] and primary term [1]",
"index_uuid": "IIq46lyCQMisw9_iPDheiw",
"shard": "0",
"index": "customer"
}
],
......
},
"status": 409
}
1)post 或 put请求都可以修改文档;
1)更新文档id为1的文档
Post localhost:9200/customer/external/1/_update
{
"doc":{ // 注意 post请求路径带update的更新的请求体不同
"name":"post_update_202210061135"
}
}
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 6,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 13,
"_primary_term": 1
}
2)再发送一次相同请求,且报文体也相同,则得到 noop ;
Post localhost:9200/customer/external/1/_update
{
"doc":{
"name":"post_update_202210061135"
}
}
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 6,
"result": "noop", // 没有做任何操作
"_shards": {
"total": 0,
"successful": 0,
"failed": 0
}
}
1)更新id等于1的文档
Post localhost:9200/customer/external/1
{
"name":"zhangsan_post_update_noupdate"
}
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 7,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 14,
"_primary_term": 1
}
2)再发一次相同请求,相同报文体,如下:
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 8,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 15,
"_primary_term": 1
}
【小结】
put请求更新文档时,其请求路径不能带 _update ;
0)初始数据:id为2的文档;
post localhost:9200/customer/external/2
{}
{
"_index": "customer",
"_type": "external",
"_id": "2",
"_version": 6,
"_seq_no": 8,
"_primary_term": 2,
"found": true,
"_source": {
"name": "post_zhangsan_02",
"addr": "post_addr_02"
}
}
1)更新id为2的文档
Put localhost:9200/customer/external/2
{
"doc":{
"name":"put_update_202210071519"
}
}
// 更新后的结果
{
"_index": "customer",
"_type": "external",
"_id": "2",
"_version": 7,
"_seq_no": 9,
"_primary_term": 2,
"found": true,
"_source": {
"doc": {
"name": "put_update_202210071519"
}
}
}
【小结】
1)为id为1的文档新增 addr 字段;
Post localhost:9200/customer/external/1
{
"doc":{
"name":"post_noupdate_202210061151"
, "addr":"成都高新区01_post_新增属性"
}
}
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 11,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 18,
"_primary_term": 1
}
1)为id为1的文档新增 addr 字段;
Put localhost:9200/customer/external/1
{
"doc":{
"name":"post_noupdate_202210061154"
, "addr":"成都高新区02_put_新增属性"
}
}
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 12,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 19,
"_primary_term": 1
}
1)post请求路径带_update,仅部分更新(我想大部分场景应该选择带 _update)
2)post请求路径不带update,是全量覆盖
3)例子(post请求带与不带_update 更新文档的区别):
3.0)初始数据
get localhost:9200/customer/external/2
{}
{
"_index": "customer",
"_type": "external",
"_id": "2",
"_version": 6,
"_seq_no": 24,
"_primary_term": 1,
"found": true,
"_source": {
"name": "zhangsan2_insert",
"addr": "post_带update_成都04"
}
}
3.1)Post请求路径带update的部分更新 ;
Post localhost:9200/customer/external/2/_update
{
"doc":{
"addr":"post_带update_成都05"
}
}
// 更新后的结果(部分更新):
{
"_index": "customer",
"_type": "external",
"_id": "2",
"_version": 7,
"_seq_no": 25,
"_primary_term": 1,
"found": true,
"_source": {
"name": "zhangsan2_insert",
"addr": "post_带update_成都05"
}
}
3.2)post请求路径不带_update 的全量替换 ;
Post localhost:9200/customer/external/2
{
"addr":"post_不带update_成都06"
}
// 更新后的结果(全量替换):
{
"_index": "customer",
"_type": "external",
"_id": "2",
"_version": 8,
"_seq_no": 26,
"_primary_term": 1,
"found": true,
"_source": {
"addr": "post_不带update_成都06" // (显然,这里是全量替换)
}
}
1)删除文档id为2的文档
Delete localhost:9200/customer/external/2
{
"_index": "customer",
"_type": "external",
"_id": "2",
"_version": 9,
"result": "deleted", // 删除成功
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 27,
"_primary_term": 1
}
2)删除完成后,再次查询id为2的文档,如下:
Get localhost:9200/customer/external/2
{}
{
"_index": "customer",
"_type": "external",
"_id": "2",
"found": false // 显然没有找到
}
注意: es中没有提供删除类型的api ;
1)删除customer索引;
Delete localhost:9200/customer
{
"acknowledged": true
}
2)删除索引文档后,,再次查询(报索引不存在);
Get localhost:9200/customer/external/2
{}
{
"error": {
"root_cause": [
{
"type": "index_not_found_exception",
"reason": "no such index [customer]",
"resource.type": "index_expression",
"resource.id": "customer",
"index_uuid": "_na_",
"index": "customer"
}
],
......
},
"status": 404
}