参考:
https://es.xiaoleilu.com/030_Data/05_Document.html
《ELasticsearch in Action》
以下的操作在ES7.5版本下。
1. 文档
一个文档不只有数据,还包含了元数据,三个必须的元数据是:
_index: 索引,可以理解为mysql中数据库。
_type: 7.5版本后已经强制单索引单类型。
_id: 创建文档的时候可以指定,也可以不指定,es会自定生成。
2. 检索文档
2.1 指定id检索
GET /website/123?pretty
这里指定了id来检索文档,将会只返回一个结果。同时返回的结果中将包括_source自定,其内容是我们新建文档123的时候发送的全部内容。
2.2 检索文档的一部分
GET /website/123?_source=title,text
返回的source里面将只会有title和text字段。
3. 检查文档知否存在
HEAD /megacorp/_doc/1
将返回200 - OK
如果不存在将返回404 - Not Found
4. 更新文档
PUT /website/_doc/123
{
"title": "My first blog entry",
"text": "I am starting to get the hang of this...",
"date": "2014/01/02"
}
存在将更新,不存在将创建。可以从返回结果的"result" : "updated",看出
{
"_index" : "website",
"_type" : "_doc",
"_id" : "12",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 3,
"_primary_term" : 1
}
Es的更新文档操作过程:
- 从旧文档中检索JSON
- 修改它
- 删除旧文档
- 索引新文档
5. 创建一个文档
如果想创建一个文档,而不是更新,使用:
POST /website/_doc/12?op_type=create
或者:
POST /website/_doc/12/_create
6. 删除一个文档
DELETE /website/_doc/12
7. 版本控制
7.1 内部版本号
每个文档都有一个_version号码,这个号码在文档被改变时加一。Elasticsearch使用这个_version保证所有修改都被正确排序。当一个旧版本出现在新版本之后,它会被简单的忽略。
我们利用_version的这一优点确保数据不会因为修改冲突而丢失。我们可以指定文档的version来做想要的更改。如果那个版本号不是现在的,我们的请求就失败了。
Let's create a new blog post: 让我们创建一个新的博文:
PUT /website/_doc/1/_create
{
"title": "My first blog entry",
"text": "Just trying this out..."
}
响应体告诉我们这是一个新建的文档,它的_version是1。现在假设我们要编辑这个文档:把数据加载到web表单中,修改,然后保存成新版本。
首先我们检索文档:
GET /website/_doc/1
响应体包含相同的_version是1
{
"_index" : "website",
"_type" : "blog",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"title": "My first blog entry",
"text": "Just trying this out..."
}
}
现在,当我们通过重新索引文档保存修改时,我们这样指定了version参数:
PUT /website/_doc/1?version=1
{
"title": "My first blog entry",
"text": "Starting to get the hang of this..."
}
7.2 外部版本号
如果主数据库有版本字段——或一些类似于timestamp等可以用于版本控制的字段——是你就可以在Elasticsearch的查询字符串后面添加version_type=external来使用这些版本号。版本号必须是整数,大于零小于9.2e+18——Java中的正的long。
外部版本号与之前说的内部版本号在处理的时候有些不同。它不再检查_version是否与请求中指定的一致,而是检查是否小于指定的版本。如果请求成功,外部版本号就会被存储到_version中
8. 局部更新
可以使用以下请求为博客添加一个tags字段和一个views字段:
POST /website/blog/1/_update
{
"doc" : {
"tags" : [ "testing" ],
"views": 0
}
}
如果文档不存在,将返回404。
8.1 更新不奴存在的文档
在这种情况下,我们可以使用upsert参数定义文档来使其不存在时被创建。
POST /website/_update/1
{
"script" : "ctx._source.views+=1",
"upsert": {
"views": 1
}
}
9. 检索多个文档
检索多个文档依旧非常快。合并多个请求可以避免每个请求单独的网络开销。如果你需要从Elasticsearch中检索多个文档,相对于一个一个的检索,更快的方式是在一个请求中使用multi-get或者mget API。
mget API参数是一个docs数组,数组的每个节点定义一个文档的_index、_type、_id元数据。如果你只想检索一个或几个确定的字段,也可以定义一个_source参数:
POST /_mget
{
"docs" : [
{
"_index" : "website",
"_id" : 2
},
{
"_index" : "megacorp",
"_id" : 1,
"_source": "views"
}
]
}
响应体也包含一个docs数组,每个文档还包含一个响应,它们按照请求定义的顺序排列。
{
"docs" : [
{
"_index" : "website",
"_type" : "blog",
"_id" : "2",
"found" : false
},
{
"_index" : "megacorp",
"_type" : "employee",
"_id" : "1",
"_version" : 2,
"_seq_no" : 1,
"_primary_term" : 1,
"found" : true,
"_source" : { }
}
]
}
10. 批量操作
为了将这些放在一起,bulk请求表单是这样的:
POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }} <1>
{ "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"} } <2>
<1> 注意delete行为(action)没有请求体,它紧接着另一个行为(action)
<2> 记得最后一个换行符
11. 搜索
为了充分挖掘Elasticsearch的潜力,你需要理解以下三个概念:
映射:Mapping,数据在每个字段中的解释说明
分析:Analysis,全部是如何处理的可以被搜索的
DSL:领域特定语言查询,es中使用的灵活的、强大的查询语言。
11.1 空搜索
GET /_search
将会返回集群中所有文档。
重要:
搜索一个索引有5个主分片和5个索引各有一个分片事实上是一样的。
11.2 简易搜索
search API有两种表单:一种是“简易版”的查询字符串(query string)将所有参数通过查询字符串定义,另一种版本使用JSON完整的表示请求体(request body),这种富搜索语言叫做结构化查询语句(DSL)。
11.3 _all字段
返回包含"mary"字符的所有文档的简单搜索:
GET /_search?q=mary
在前一个例子中,我们搜索tweet或name字段中包含某个字符的结果。然而,这个语句返回的结果在三个不同的字段中包含"mary":
用户的名字是“Mary”
“Mary”发的六个推文
针对“@mary”的一个推文
Elasticsearch是如何设法找到三个不同字段的结果的?
当你索引一个文档,Elasticsearch把所有字符串字段值连接起来放在一个大字符串中,它被索引为一个特殊的字段_all。例如,当索引这个文档:
{
"tweet": "However did I manage before Elasticsearch?",
"date": "2014-09-14",
"name": "Mary Jones",
"user_id": 1
}
这好比我们增加了一个叫做_all的额外字段值:
"However did I manage before Elasticsearch? 2014-09-14 Mary Jones 1"
若没有指定字段,查询字符串搜索(即q=xxx)使用_all字段搜索。