# 索引

## 启程

为了能让你感受一下 Elasticsearch 能做什么以及它是有多么的易用，我们会先为你简单展示一下，其中包括了基本的 *创建索引*，*搜索* 以及 *聚合*。

我们会在这里向你介绍一些新的术语以及简单的概念，即使你没有马上接受这些概念也没有关系。我们会在之后的章节中逐渐帮你理解它们。

所以，准备开始享受 Elasticsearch 的学习之旅把！

## 建立一个员工名单

想象我们正在为一个名叫 megacorp 的公司的 HR 部门制作一个新的员工名单系统，这些名单应该可以满足实时协同工作，所以它应该可以满足以下要求：

* 数据可以包含多个值的标签、数字以及纯文本内容，
* 可以检索任何职员的所有数据。
* 允许结构化搜索。例如，查找30岁以上的员工。
* 允许简单的全文搜索以及相对复杂的*短语*搜索。
* 在返回的匹配文档中高亮关键字。
* 拥有数据统计与管理的后台。

## 为员工档案创建索引

这个项目的第一步就是存储员工的数据。这样你就需要一个“员工档案”的表单，这样每个文档都代表着一个员工。在 Elasticsearch 中，存储数据的行为就叫做 *索引(indexing)* ，但是在我们索引数据前，我们需要决定将数据存储在哪里。

在 Elasticsearch 中，文档属于一种 *类型(type)*，各种各样的类型存在于一个 *索引* 中。你也可以通过类比传统的关系数据库得到一些大致的相似之处：

```
关系数据库     ⇒ 数据库 ⇒ 表    ⇒ 行    ⇒ 列(Columns)
Elasticsearch  ⇒ 索引   ⇒ 类型  ⇒ 文档  ⇒ 字段(Fields)
```

一个 Elasticsearch 集群可以包含多个 *索引*（数据库），也就是说其中包含了很多 *类型*（表）。这些类型中包含了很多的 *文档*（行），然后每个文档中又包含了很多的 *字段*（列）。

> ### 索引 索引 索引

你可能发现在 Elasticsearch 中，索引这个词汇已经被赋予了太多意义，所以在这里我们有必要澄清一下：

> 索引 (名词)

如上文所说，一个 *索引* 就类似于传统关系型数据库中的 *数据库*。这里就是存储相关文档的的地方。

> 索引 (动词)

*为一个文档创建索引* 是把一个文档存储到一个*索引(名词)*&#x4E2D;的过程，这样它才能被检索。这个过程非常类似于 SQL 中的 `INSERT` 命令，如果已经存在文档，新的文档将会覆盖旧的文档。

> 反向索引

在关系数据库中的某列添加一个 *索引*，比如多路搜索树(B-Tree)索引，就可以加速数据的取回速度， Elasticsearch 以及 Lucene 使用的是一个叫做 *反向索引(inverted index)* 的结构来实现相同的功能。

> 通常，每个文档中的字段都被创建了索引（拥有一个反向索引），因此他们可以被搜索。如果一个字段缺失了反向索引的话，它将不能被搜索。我们将会在之后的《反向索引》章节中详细介绍它。

所以为了创建员工名单，我们需要进行如下操作：

* 为每一个员工的 *文档* 创建索引，每个 *文档* 都包含了一个员工的所有信息。
* 每个文档都会被标记为 `employee` *类型*。
* 这种类型将存活在 `megacorp` 这个 *索引* 中。
* 这个索引将会存储在 Elasticsearch 的集群中

在实际的操作中，这些操作是非常简单的（即使看起来有这么多步骤）。我们可以把如此之多的操作通过一个命令来完成：

```javascript
PUT /megacorp/employee/1
{
    "first_name" : "John",
    "last_name" :  "Smith",
    "age" :        25,
    "about" :      "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}
```

注意在 `/megacorp/employee/1` 路径下，包含了三个部分：

| 名字           | 内容      |
| ------------ | ------- |
| **megacorp** | 索引的名字   |
| **employee** | 类型的名字   |
| **1**        | 当前员工的ID |

请求部分，也就是 JSON 文档，在这里包含了关于这名员工的所有信息。他的名字是 “John Smith”，他已经25岁了，他很喜欢攀岩。

怎么样？很简单吧！我们在操作前不需要进行任何管理操作，比如创建索引，或者为字段指定数据的类型。我们就这么直接地为一个文档创建了索引。Elasticsearch 会在创建的时候为它们设定默认值，所以所有管理操作已经在后台被默默地完成了。

在进行下一步之前，我们再为这个目录添加更多的员工信息吧：

```javascript
PUT /megacorp/employee/2
{
    "first_name" :  "Jane",
    "last_name" :   "Smith",
    "age" :         32,
    "about" :       "I like to collect rock albums",
    "interests":  [ "music" ]
}

PUT /megacorp/employee/3
{
    "first_name" :  "Douglas",
    "last_name" :   "Fir",
    "age" :         35,
    "about":        "I like to build cabinets",
    "interests":  [ "forestry" ]
}
```
