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遵循与之前所说全然同样的过程,这个步骤例如以下:

  1. 从旧文档中检索JSON
  2. 改动它
  3. 删除旧文档
  4. 索引新文档

唯一的不同是​​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将会在你之后加入很多其它索引的时候才会在后台进行删除内容的清理。