Elastcisearch 是分布式的 文档 存储。它能存储和检索复杂的数据结构--序列化成为JSON文档--以 实时 的方式。所以我们关心的就是在 Elasticsearch 中怎样安全的存储文档,以及如何将文档再次返回。官方文档上对 文档 进行了解释。
键:可以是字段或是字段的名称
值:可以是一个字符串、一个数字、一个布尔值、另一个对象、一些数组值、其他特殊类型的字符串、或代表一个地理位置的对象。
{ "name": "John Smith", "age": 42, "confirmed": true, "join_date": "2014-06-01", "home": { "lat": 51.5, "lon": 0.1 }, "accounts": [ { "type": "facebook", "id": "johnsmith" }, { "type": "twitter", "id": "johnsmith" } ] }
自定义或自动生成ID:
使用自定义ID时,需要使用 PUT 谓词,并指定索引、类型、ID;若需要自动生成ID,需要使用POST谓词,并指定索引和类型,自动生成的 ID 是 URL-safe、 基于 Base64 编码且长度为20个字符的 GUID 字符串。
创建新文档:
前文已经介绍了最简单的创建文档的方法,但是很多情况下,我们会有当ID不存在时才存入数据的需求,并不去覆盖现有的数据。
方法一:(不指定ID,由Elasticsearch生成_id)
POST new_retail/spu{ ... }
方法二:使用op_type查询
PUT new_retail/spu/1?op_type=create{ ... }
方法三:
PUT new_retail/spu/1/_create{ ... }
每次对文档进行增加、删除、更新操作时,都会增加文档的_version值,包括删除不存在的ID时,version值也会增加。我们可以使用_version值确保应用中互相冲突的。
更新文档:
在更新文档的过程中,由于文档是不可变的,只能被替换不能修改,所以实际上Elasticsearch进行了以下的步骤:
- 从旧文档构建 JSON
- 更改该 JSON
- 删除旧文档
- 索引一个新文档
增加新的字段:
方法一:POST new_retail/spu/1/_update{
"doc":{
"view":"1"
}
}方法二:Post new_retail/spu/_update{
"script":"ctx._source.view=\"1\""
}
删除字段:
POST new_retail/spu/1/_update{
"script":"ctx._source.remove(\"brand_code\")"
}
部分更新字段:(通过脚本更新字段)
POST new_retail/spu/1/_update{
"script" : "ctx._source.view+=1","upsert" : {"view":1}
}
其中,使用upsert参数,如果对应文档不存在,就先创建它。对于一些应用场景,文档被更新了也没关系,比如对页面的访问量计数器进行递增操作,此时两个线程同时对计数器进行操作,发生冲突时需要尝试再更新。retry_on_conflict参数规定了冲突后重试的次数。POST new_retail/spu/1/_update?retry_on_conflict=5 表示重试5次
也可以通过脚本为一个数组增加新的标签。
POST new_retail/spu/1/_update{
"script" : "ctx._source.tags+=newTag",
"params" : {
"newTag" : "hot"
}
}
通过脚本也可以进行删除文档:
POST new_retail/spu/1/_update{
"script" : "if(ctx._source.tags.contains("hot")){ctx.op = 'delete'}else{ctx.op = 'none'}"
}
检索文档:
最简单的检索一个文档就是直接通过指定ID GET,如果需要检索多个文档,可以使用mget将多个文档封装到一个请求中。
GET _mget{
"docs":[
{
"_index": "new_retail",
"_type" : "spu",
"_id" : 1
},
{
"_index": "new_retail",
"_type" : "spu",
"_id" : 2
}
]
}
如果需要检索的多个文档属于同一个_index或者同一个_type中,可以直接在URL中指定(new_retail/spu/_mget)。如果_type都相同,可以直接传id数组,而不是整个文档。
GET new_retail/spu/_mget{ "ids" : [ "2", "1" ] }
注:批量查找时,如果有一个ID对应的文档不存在,也会返回可检索到的其他文档,状态码为200,不会影响其他文档的检索。
ES批量操作bluk:
bluk允许在单个操作中进行不同的create/delete/update/index操作。其请求体如下:
{ action: { metadata }}\n { request body }\n { action: { metadata }}\n { request body }\n ...
每行必须以换行符结束,可以有效的分割行。
action/metadata行指定,哪个文档做什么操作。
action:可为create(如果文档不存在,则创建一个新文档)、update(部分更新文档)、delete、index(创建一个新文档或者替换现有文档)。metadata指定操作的_index、_type、_id。request body为请求的主体,为_source包含的字段和值,是index和create操作必须的参数。以下是官方文档给出的一个例子:
POST /_bulk { "delete": { "_index": "website", "_type": "blog", "_id": "123" }} { "create": { "_index": "website", "_type": "blog", "_id": "123" }} { "title": "My first blog post" } { "index": { "_index": "website", "_type": "blog" }} { "title": "My second blog post" } { "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} } { "doc" : {"title" : "My updated blog post"} }
delete后面不能有请求体。
最后也需要一个换行符
当然,bulk也可以将index和type放到URL中指定。
使用_bulk进行批量操作数据时,不是原子的,一条失败,不会影响其他操作,因此不能用它来进行事务控制。