本篇文章是我学习Elasticsearch的学习笔记,文章比较简单,因为我坚信学一门新技术的最快方式就是先掌握这门技术的增删改查再慢慢深入学习更高级的用法。
简介Elasticsearch是一个分布式文档存储。Elasticsearch 不是将信息存储为列式数据行,而是存储已序列化为 JSON 文档的复杂数据结构。(以下都称Elasticsearch为es)
把es和mysql对照学习的话,理解起来比较容易
在es中,并没有数据库、数据表和数据行这么概念,取而代之的是:
- index索引
相当于mysql中的databasetype类型
相当于mysql中的tabledocument文档
相当于mysql中的一行数据
在es中,增有两种方式,PUT和POST
具体的区别会在下边说明:
(不想听废话的:PUT和POST虽然都有新增和修改的作用,但PUT倾向于修改且发送PUT请求不带id会报错,POST更倾向于添加操作,不加id的话es会提我们自己生成)
PUT /customer/external/2
{
"name": "jack"
}
result:
{
"_index" : "customer",
"_type" : "external",
"_id" : "2",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 9,
"_primary_term" : 1
}
我们此时再进行一次请求,这次不同的是把"jack"改为"xiaoli"
{
"_index" : "customer",
"_type" : "external",
"_id" : "2",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 10,
"_primary_term" : 1
}
此时我们发现result的值变为了updated,相信聪明的读者们已经明白了,第一次请求是新增操作,第二次就是修改操作
那这时候,有朋友会思考,那跟POST的区别是什么呢
别急别急,我们先来看一下POST请求
post /customer/external/11
{
"name": "hong"
}
{
"_index" : "customer",
"_type" : "external",
"_id" : "11",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 19,
"_primary_term" : 1
}
别说话,也别吻我,我们再发一次请求
{
"_index" : "customer",
"_type" : "external",
"_id" : "11",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 20,
"_primary_term" : 1
}
那有朋友到这里就要问了,这和PUT不是没区别吗,你是不是想水文章长度啊!!!还真不是(捂脸哭)
我们再发送一次POST请求但是把id去掉呢
post /customer/external
{
"name": "hong"
}
{
"_index" : "customer",
"_type" : "external",
"_id" : "210Utn8BVKsYGviL9qDz",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 17,
"_primary_term" : 1
}
这时我们就会发现,es这次会帮我们生成一个随机的_id
让我们看看PUT请求不加id,会发生什么神奇的反应呢?
PUT /customer/external
{
"name": "xiaoli"
}
当当当当
{
"error": "Incorrect HTTP method for uri [/customer/external?pretty] and method [PUT], allowed: [POST]",
"status": 405
}
直接报错了,es都会提醒我们让我们用POST请求
删DELETE /customer/external/{id}
DELETE /customer
查
GET /customer/external/{id}
_version和_seq_no的作用和区别
在我们对document进行PUT或POST操作之后,我们总会发现有两个属性一直在变化,也就是_version和_seq_no,那它俩为啥那么特殊呢,别的不变就它俩变?
(不想听废话的:_version是document的版本,而_seq_no更像是index的版本,只是这样比喻好理解,并不是代表实际逻辑)
接下来就是解释为啥就它俩不老实的原因啦:
- _version:
官方文档的解释为:
(integer) The document version associated with the operation. The document version is incremented each time the document is updated.
This parameter is only returned for successful actions.
谷歌翻译:
(整数)与操作关联的文档版本。每次更新文档时,文档版本都会递增。
此参数仅返回成功的操作。_seq_no:
官方文档的解释为:
(integer) The sequence number assigned to the document for the operation. Sequence numbers are used to ensure an older version of a document doesn’t overwrite a newer version. See Optimistic concurrency control.
This parameter is only returned for successful operations.
谷歌翻译:
(整数)分配给文档的序列号进行操作。序列号用于确保旧版本的文档不会覆盖更新版本。请参阅乐观的并发控制。
此参数仅返回成功操作。
好吧,不管是中文还是英文,都看不懂。。。
啊哈哈哈,代码来喽~~~这看代码,多是一件美事啊~
首先,我们来新加一个document
POST /customer/_doc/30 这里和上边的不一样,只是es一直在报Deprecation这个错误,es推荐使用这种请求路径而已
{
"name": "xiaoli"
}
这鸡汤,啊不,这json多新鲜啊~
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "30",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 61,
"_primary_term" : 1
}
这里我们就可以看出_version 和_seq_no的区别,但是还是有点懵,对吧 ,来来来,咱们接着往下走
我们在同一个index中新增一个document
POST /customer/_doc/31
{
"name": "xiaoli"
}
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "31",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 62,
"_primary_term" : 1
}
看看看,这次只有_seq_no进行了变化,而_version是1,再结合上边官方给出的解释,其实我们就可以知道他们两个的区别啦
那这样做的好处是什么呢?_version给我们最直观的感受就是让我们知道了,这个document到底成功更新了几次,而_seq_no就可以用来做乐观锁
接下来我们还用最直观的代码来看
我们先进行一次
POST /customer/_doc/30
{
"name": "xiaoli"
}
这时可以看到我们的"_seq_no" : 65
那我们现在模拟一下同时两个线程来进行同一个document的修改,如何保证只有一个线程可以正确的进行修改呢
我们可以使用
POST /customer/_doc/30?if_seq_no=65&if_primary_term=1
{
"name": "xiaoli"
}
如果请求中的_seq_no和我们当前的_seq_no一致的话,并会修改成功,但如果不一致的话,就会出错
{
"error": {
"root_cause": [
{
"type": "version_conflict_engine_exception",
"reason": "[30]: version conflict, required seqNo [65], primary term [1]. current document has seqNo [66] and primary term [1]",
"index_uuid": "ZZFoSyauQUCPZzPSDEuSLw",
"shard": "0",
"index": "customer"
}
],
"type": "version_conflict_engine_exception",
"reason": "[30]: version conflict, required seqNo [65], primary term [1]. current document has seqNo [66] and primary term [1]",
"index_uuid": "ZZFoSyauQUCPZzPSDEuSLw",
"shard": "0",
"index": "customer"
},
"status": 409
}



