Elasticsearch是一个分布式的文档(document)存储引擎。它能够实时存储并检索复杂数据结构——序列化的JSON文档。换言说,一旦文档被存储在Elasticsearch中,它就能够在集群的任一节点上被检索。
当然,我们不仅须要存储数据。还要高速的批量查询。尽管已经有非常多NoSQL的解决方式同意我们以文档的形式存储对象,但它们依然须要考虑怎样查询这些数据,以及哪些字段须要被索引以便检索时更加高速。
程序中大多的实体或对象可以被序列化为包括键值对的JSON对象,键(key)是字段(field)或属性(property)的名字,值(value)可以是字符串、数字、波尔类型、还有一个对象、值数组或者其它特殊类型,比方表示日期的字符串或者表示地理位置的对象。
文档元数据(Document MetaData):
一个文档不仅仅有数据。它还包括了元数据(metadata)——关于文档的信息。
三个必须的元数据节点是:
节点 | 说明 |
---|---|
_index |
文档存储的地方 |
_type |
文档代表的对象的类 |
_id |
文档的唯一标识 |
_index
索引(index)类似于关系型数据库里的“数据库”——它是我们存储和索引关联数据的地方。
其实,我们的数据被存储和索引在分片(shards)中,索引仅仅是一个把一个或多个分片分组在一起的逻辑空间。然而,这仅仅是一些内部细节——我们的程序全然不用关心分片。对于我们的程序而言,文档存储在索引(index)中。剩下的细节由Elasticsearch关心既可。
后面会继续探讨怎样创建并管理索引。但如今,我们将让Elasticsearch为我们创建索引。我们唯一须要做的不过选择一个索引名。这个名字必须是所有小写。不能下面划线开头,不能包括逗号。
让我们使用website
做为索引名。
_type
在应用中。我们使用对象表示一些“事物”。比如一个用户、一篇博客、一个评论,或者一封邮件。每一个对象都属于一个类(class),这个类定义了属性或与对象关联的数据。user
类的对象可能包括姓名、性别、年龄和Email地址。
在关系型数据库中,我们常常将同样类的对象存储在一个表里。由于它们有着同样的结构。同理,在Elasticsearch中,我们使用同样类型(type)的文档表示同样的“事物”。由于他们的数据结构也是同样的。
每一个类型(type)都有自己的映射(mapping)或者结构定义。就像传统数据库表中的列一样。全部类型下的文档被存储在同一个索引下,可是类型的映射(mapping)会告诉Elasticsearch不同的文档怎样被索引。 我们将会在《映射》章节探讨怎样定义和管理映射。可是如今我们将依赖ELasticsearch去自己主动处理数据结构。
_type
的名字能够是大写或小写,不能包括下划线或逗号。
我们将使用blog
做为类型名。
_id
id不过一个字符串。它与_index
和_type
组合时。就能够在ELasticsearch中唯一标识一个文档。
当创建一个文档。你能够自己定义_id
,也能够让Elasticsearch帮你自己主动生成。
ps:还有其他部分其他元数据,兴许再介绍。
使用自己的ID
假设你的文档有自然的标识符(比如user_account
字段或者其它值表示文档)。你就能够提供自己的_id
,使用这样的形式的index
API:
PUT /{index}/{type}/{id}
{"key": "value"...}
如,PUT /website/blog/123
{
"title": "My blog entry",
"text": "汉语你能够。。 ",
"date": "2015/07/16"
}
{
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 5,
"created": false
}
Elasticsearch中每一个文档都有版本,每当文档变化(包含删除)都会使_version
添加。兴许我们将探讨怎样使用_version
号确保你程序的一部分不会覆盖掉还有一部分所做的更改。
自增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": "2015/07/16"
}
响应内容与刚才类似。仅仅有_id
字段变成了自己主动生成的值:
{
"_index": "website",
"_type": "blog",
"_id": "AU6Vi9GsUzILmCnC2hkX",
"_version": 1,
"created": true
}
更新整个文档
文档在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>
}
- <1>
created
标识为false
由于同索引、同类型下已经存在同ID的文档。
在内部,Elasticsearch已经标记旧文档为删除并加入了一个完整的新文档。
旧版本号文档不会马上消失。但你也不能去訪问它。Elasticsearch会在你继续索引很多其它数据时清理被删除的文档。
在后面探讨update
API。这个API 似乎 同意你改动文档的局部。但其实Elasticsearch遵循与之前所说全然同样的过程,这个步骤例如以下:
- 从旧文档中检索JSON
- 改动它
- 删除旧文档
- 索引新文档
唯一的不同是update
API完毕这一过程仅仅须要一个client请求既可。不再须要get
和index
请求了。
删除文档
删除文档的语法模式与之前基本一致,仅仅只是要使用DELETE
方法:
DELETE /website/blog/1234
假设文档被找到,Elasticsearch将返回200 OK
状态码和下面响应体。注意_version
数字已经添加了。
{
"found" : true,
"_index" : "website",
"_type" : "blog",
"_id" : "1234",
"_version" : 3
}
假设文档未找到。我们将得到一个404 Not Found
状态码,响应体是这种:
{
"found" : false,
"_index" : "website",
"_type" : "blog",
"_id" : "1234",
"_version" : 4
}
虽然文档不存在——"found"的值是false——_version依然添加了。
这是内部记录的一部分。它确保在多节点间不同操作能够有正确的顺序。
删除一个文档也不会马上从磁盘上移除,它仅仅是被标记成已删除。
Elasticsearch将会在你之后加入很多其它索引的时候才会在后台进行删除内容的清理。