1 .什么是文档
在 Elasticsearch 中,术语文档有着特定的含义。它是指最顶层或者根对象, 这个根对象被序列化成 JSON 并存储到 Elasticsearch 中,指定了唯一 ID。
2.文档元数据
一个文档不仅仅包含它的数据,也包含元数据——有关文档的信息。三个必须的元数据元素如下:
-
_index
文档在哪存放 -
_type
文档表示的对象类别 -
_id
文档唯一标识
其他元数据另做介绍
3. 索引文档
一个文档的上面三个元数据唯一标识一个文档。我们可以自己提供_id
,也可以让index API自动生成。
PUT /{index}/{type}/{id}
{
"field": "value",
...
}
示例:
PUT /website/blog/123
{
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
返回值:
{
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 1,
"created": true
}
如果没有提供_id
,Elasticsearch 可以帮我们自动生成 ID 。
POST /website/blog/
{
"title": "My second blog entry",
"text": "Still trying this out...",
"date": "2014/01/01"
}
返回值:
{
"_index": "website",
"_type": "blog",
"_id": "AVFgSgVHUP18jI2wRx0w",
"_version": 1,
"created": true
}
自动生成的 ID 是 URL-safe、 基于 Base64 编码且长度为20个字符的 GUID 字符串.
4.取回一个文档
GET /website/blog/123?pretty
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 1,
"found" : true,
"_source" : {
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
}
如果我们请求一个不存在的文档,我们仍旧会得到一个 JSON 响应体.
curl -i -XGET http://localhost:9200/website/blog/124?pretty
响应:
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=UTF-8
Content-Length: 83
{
"_index" : "website",
"_type" : "blog",
"_id" : "124",
"found" : false
}
3.1 返回文档的一部分
默认情况下, GET
请求会返回整个文档,这个文档正如存储在_source
字段中的一样。但是也许你只对其中的title
字段感兴趣。单个字段能用_source
参数请求得到,多个字段也能使用逗号分隔的列表来指定。
GET /website/blog/123?_source=title,text
响应:
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 1,
"found" : true,
"_source" : {
"title": "My first blog entry" ,
"text": "Just trying this out..."
}
}
或者,如果你只想得到 _source 字段,不需要任何元数据,你能使用 _source 端点:
GET /website/blog/123/_source
响应:
{
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
4.更新整个文档
在 Elasticsearch 中文档是不可改变的,不能修改它们。相反,如果想要更新现有的文档,需要重建索引或者进行替换,我们可以使用相同的 index
API 进行实现
PUT /website/blog/123
{
"title": "My first blog entry",
"text": "I am starting to get the hang of this...",
"date": "2014/01/02"
}
响应:
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 2,
"created": false
}
在内部,Elasticsearch 已将旧文档标记为已删除,并增加一个全新的文档。尽管你不能再对旧版本的文档进行访问,但它并不会立即消失。当继续索引更多的数据,Elasticsearch 会在后台清理这些已删除文档。
5.创建新文档
_index
、 _type
和 _id
的组合可以唯一标识一个文档。所以,确保创建一个新文档的最简单办法是,使用索引请求的POST
形式让 Elasticsearch 自动生成唯一_id
:
POST /website/blog/
{ ... }
然而,如果已经有自己的 _id ,那么我们必须告诉 Elasticsearch ,只有在相同的 _index 、 _type 和 _id 不存在时才接受我们的索引请求。这里有两种方式,他们做的实际是相同的事情。使用哪种,取决于哪种使用起来更方便。
PUT /website/blog/123/_create
{ ... }
如果创建新文档的请求成功执行,Elasticsearch 会返回元数据和一个201 Created
的 HTTP 响应码。另一方面,如果具有相同的_index
、_type
和_id
的文档已经存在,Elasticsearch 将会返回409 Conflict
响应码,以及如下的错误信息:
{
"error": {
"root_cause": [
{
"type": "document_already_exists_exception",
"reason": "[blog][123]: document already exists",
"shard": "0",
"index": "website"
}
],
"type": "document_already_exists_exception",
"reason": "[blog][123]: document already exists",
"shard": "0",
"index": "website"
},
"status": 409
}
6.删除文档
删除文档的语法和我们所知道的规则相同,只是使用DELETE
方法:DELETE /website/blog/123
如果找到该文档,
{
"found" : true,
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 3
}
如果文档没有找到,
{
"found" : false,
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 4
}
7.空搜索
GET /_search
响应
{
"hits" : {
"total" : 14,
"hits" : [
{
"_index": "us",
"_type": "tweet",
"_id": "7",
"_score": 1,
"_source": {
"date": "2014-09-17",
"name": "John Smith",
"tweet": "The Query DSL is really powerful and flexible",
"user_id": 2
}
},
... 9 RESULTS REMOVED ...
],
"max_score" : 1
},
"took" : 4,
"_shards" : {
"failed" : 0,
"successful" : 10,
"total" : 10
},
"timed_out" : false
}
返回结果中最重要的部分是 hits
,它包含total
字段来表示匹配到的文档总数,并且一个hits
数组包含所查询结果的前十个文档。
max_score
值是与查询所匹配文档的 _score
的最大值 。took
值 告诉我们执行整个搜索请求耗费了多少毫秒._shards
部分 告诉我们在查询中参与分片的总数, 以及这些分片成功了多少个失败了多少个。正常情况下我们不希望分片失败,但是分片失败是可能发生的。如果我们遭遇到一种灾难级别的故障,在这个故障中丢失了相同分片的原始数据和副本,那么对这个分片将没有可用副本来对搜索请求作出响应。假若这样,Elasticsearch 将报告这个分片是失败的,但是会继续返回剩余分片的结果。timed_out
值告诉我们查询是否超时。默认情况下,搜索请求不会超时。 如果低响应时间比完成结果更重要,你可以指定 timeout
为 10 或者 10ms(10毫秒),或者 1s(1秒):
GET /_search?timeout=10ms
应当注意的是 timeout
的节点返回到目前为止收集的结果并且关闭连接。在后台,其他的分片可能仍在执行查询即使是结果已经被发送了。使用超时是因为 SLA(服务等级协议)对你是很重要的,而不是因为想去中止长时间运行的查询。
8多索引,多类型
如果不对某一特殊的索引或者类型做限制,就会搜索集群中的所有文档。Elasticsearch 转发搜索请求到每一个主分片或者副本分片,汇集查询出的前10个结果,并且返回给我们。然而,经常的情况下,你想在一个或多个特殊的索引并且在一个或者多个特殊的类型中进行搜索。我们可以通过在URL中指定特殊的索引和类型达到这种效果,如下所示:
/gb/_search # 在 gb 索引中搜索所有的类型
/g*,u*/_search # 在任何以 g 或者 u 开头的索引中搜索所有的类型
/gb/user/_search # 在 gb 索引中搜索 user 类型
/_all/user,tweet/_search # 在所有的索引中搜索 user 和 tweet 类型
当在单一的索引下进行搜索的时候,Elasticsearch 转发请求到索引的每个分片中,可以是主分片也可以是副本分片,然后从每个分片中收集结果。多索引搜索恰好也是用相同的方式工作的--只是会涉及到更多的分片。