1 索引一个文档
将数据存储至es。
关于文档ID
文档通过index
API被索引——使数据可以被存储和搜索。但是首先我们需要决定文档所在。正如我们讨论的,文档通过其_index
、_type
、_id
唯一确定。们可以自己提供一个_id
,或者也使用index
API 为我们生成一个。
使用自己的ID
如果你的文档有自然的标识符(例如user_account
字段或者其他值表示文档),你就可以提供自己的_id
,使用这种形式的index
API:
PUT /{index}/{type}/{id}
{
"field": "value",
...
}
例如我们的索引叫做“website”
,类型叫做“blog”
,我们选择的ID是“123”
,那么这个索引请求就像这样:
PUT /website/blog/123
{
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
Elasticsearch的响应:
{
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 1,
"created": true
}
响应指出请求的索引已经被成功创建,这个索引中包含_index
、_type
和_id
元数据,以及一个新元素:_version
。
Elasticsearch中每个文档都有版本号,每当文档变化(包括删除)都会使_version
增加。在《版本控制》章节中我们将探讨如何使用_version
号确保你程序的一部分不会覆盖掉另一部分所做的更改。
es自增ID
如果我们的数据没有自然ID,我们可以让Elasticsearch自动为我们生成。请求结构发生了变化:PUT
方法——“在这个URL中存储文档”
变成了POST
方法——"在这个类型下存储文档"
。(译者注:原来是把文档存储到某个ID对应的空间,现在是把这个文档添加到某个_type
下)。
URL现在只包含_index
和_type
两个字段:
POST /website/blog/
{
"title": "My second blog entry",
"text": "Still trying this out...",
"date": "2014/01/01"
}
响应内容与刚才类似,只有_id
字段变成了自动生成的值:
{
"_index": "website",
"_type": "blog",
"_id": "wM0OSFhDQXGZAWDf0-drSA",
"_version": 1,
"created": true
}
自动生成的ID有22个字符长,URL-safe, Base64-encoded string universally unique identifiers, 或者叫 UUIDs。
2 检索文档
想要从Elasticsearch中获取文档,我们使用同样的_index
、_type
、_id
,但是HTTP方法改为GET
:
GET /website/blog/123?pretty
注意:7.X 版本后type 不推荐使用。如果使用上述url会提示
#! Deprecation: [types removal] Specifying types in document get requests is deprecated, use the /{index}/_doc/{id} endpoint instead.
{
"_index" : "megacorp",
"_type" : "employee",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
...
}
}
因此建议使用:
GET /website/_doc/123?pretty
pretty
在任意的查询字符串中增加pretty
参数,类似于上面的例子。会让Elasticsearch美化输出(pretty-print)JSON响应以便更加容易阅读。_source
字段不会被美化,它的样子与我们输入的一致。
返回字段解释
{
"_index" : "website", //索引
"_type" : "blog", //类型
"_id" : "123", //id
"_version" : 1, //版本
"found" : true, //是否查询到结果
"_source" : { //原始文档
...
}
}
检索文档的一部分
通常,GET
请求将返回文档的全部,存储在_source
参数中。但是可能你感兴趣的字段只是title
。请求个别字段可以使用_source
参数。多个字段可以使用逗号分隔:
GET /website/blog/123?_source=title,text
_source
字段现在只包含我们请求的字段,而且过滤了date
字段:
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 1,
"exists" : true,
"_source" : {
"title": "My first blog entry" ,
"text": "Just trying this out..."
}
}
或者你只想得到_source
字段而不要其他的元数据,你可以这样请求:
GET /website/blog/123/_source
它仅仅返回:
{
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
检查文档是否存在
如果你想做的只是检查文档是否存在——你对内容完全不感兴趣——使用HEAD
方法来代替GET
。HEAD
请求不会返回响应体,只有HTTP头:
curl -i -XHEAD http://localhost:9200/website/blog/123
Elasticsearch将会返回200 OK
状态如果你的文档存在:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 0
如果不存在返回404 Not Found
:
curl -i -XHEAD http://localhost:9200/website/blog/124
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=UTF-8
Content-Length: 0
当然,这只表示你在查询的那一刻文档不存在,但并不表示几毫秒后依旧不存在。另一个进程在这期间可能创建新文档。
更新整个文档
文档在Elasticsearch中是不可变的——我们不能修改他们。如果需要更新已存在的文档,我们可以使用《索引文档》章节提到的index
API 重建索引(reindex) 或者替换掉它。
PUT /website/blog/123
{
"title": "My first blog entry",
"text": "I am starting to get the hang of this...",
"date": "2014/01/02"
}
在响应中,我们可以看到Elasticsearch把_version
增加了。
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 2,
"created": false <1>
}
created
标识为false
因为同索引、同类型下已经存在同ID的文档。
在内部,Elasticsearch已经标记旧文档为删除并添加了一个完整的新文档。旧版本文档不会立即消失,但你也不能去访问它。Elasticsearch会在你继续索引更多数据时清理被删除的文档。
在本章的后面,我们将会在《局部更新》中探讨update
API。这个API 似乎 允许你修改文档的局部,但事实上Elasticsearch遵循与之前所说完全相同的过程,这个过程如下:
- 从旧文档中检索JSON
- 修改它
- 删除旧文档
- 索引新文档
唯一的不同是update
API完成这一过程只需要一个客户端请求既可,不再需要get
和index
请求了。