Elasticsearch学习笔记
---恢复内容开始---
取得多个文档
使用 multi-get 或者 mget API 来将这些检索请求放在一个请求中,将比逐个文档请求更快地检索到全部文档。mget API 要求有一个 docs 数组作为参数,每个 元素包含需要检索文档的元数据, 包括 _index 、 _type和 _id 。如果你想检索一个或者多个特定的字段,那么你可以通过 _source 参数来指定这些字段的名字:
GET /_mget
{
"docs" : [
{
"_index" : "website",
"_type" : "blog",
"_id" : 2
},
{
"_index" : "website",
"_type" : "pageviews",
"_id" : 1,
"_source": "views"
}
]
}
响应体:
{
"docs" : [
{
"_index" : "website",
"_id" : "2",
"_type" : "blog",
"found" : true,
"_source" : {
"text" : "This is a piece of cake...",
"title" : "My first external blog entry"
},
"_version" : 10
},
{
"_index" : "website",
"_id" : "1",
"_type" : "pageviews",
"found" : true,
"_version" : 2,
"_source" : {
"views" : 2
}
}
]
}
bulk 与其他的请求体格式稍有不同,如下所示:
{ action: { metadata }}\n
{ request body }\n
{ action: { metadata }}\n
{ request body }\n
...
这种格式类似一个有效的单行 JSON 文档 流 ,它通过换行符(\n)连接到一起。注意两个要点:
- 每行一定要以换行符(
\n)结尾, 包括最后一行 。这些换行符被用作一个标记,可以有效分隔行。 - 这些行不能包含未转义的换行符,因为他们将会对解析造成干扰。这意味着这个 JSON 不 能使用 pretty 参数打印。
action/metadata 行指定 哪一个文档 做 什么操作 。
metadata 应该 指定被索引、创建、更新或者删除的文档的 _index 、 _type 和 _id 。
例如,一个 delete 请求看起来是这样的:
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
request body 行由文档的 _source 本身组成--文档包含的字段和值。它是 index 和 create 操作所必需的,这是有道理的:你必须提供文档以索引。
它也是 update 操作所必需的,并且应该包含你传递给 update API 的相同请求体: doc 、 upsert 、 script 等等。 删除操作不需要 request body 行。
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "My first blog post" }
如果不指定 _id ,将会自动生成一个 ID :
{ "index": { "_index": "website", "_type": "blog" }}
{ "title": "My second blog post" }
为了把所有的操作组合在一起,一个完整的 bulk 请求 有以下形式:
POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "My first blog post" }
{ "index": { "_index": "website", "_type": "blog" }}
{ "title": "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} }
这个 Elasticsearch 响应包含 items 数组, 这个数组的内容是以请求的顺序列出来的每个请求的结果。
{
"took": 4,
"errors": false,
"items": [
{ "delete": {
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 2,
"status": 200,
"found": true
}},
{ "create": {
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 3,
"status": 201
}},
{ "create": {
"_index": "website",
"_type": "blog",
"_id": "EiwfApScQiiy7TIKFxRCTw",
"_version": 1,
"status": 201
}},
{ "update": {
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 4,
"status": 200
}}
]
}
每个子请求都是独立执行,因此某个子请求的失败不会对其他子请求的成功与否造成影响。 如果其中任何子请求失败,最顶层的 error 标志被设置为 true ,并且在相应的请求报告出错误明细:
POST /_bulk
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "Cannot create - it already exists" }
{ "index": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "But we can update it" }
在响应中,我们看到 create 文档 123 失败,因为它已经存在。但是随后的 index 请求,也是对文档 123操作,就成功了:
{
"took": 3,
"errors": true,
"items": [
{ "create": {
"_index": "website",
"_type": "blog",
"_id": "123",
"status": 409,
"error": "DocumentAlreadyExistsException
[[website][4] [blog][123]:
document already exists]"
}},
{ "index": {
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 5,
"status": 200
}}
]
}
这也意味着 bulk 请求不是原子的: 不能用它来实现事务控制。每个请求是单独处理的,因此一个请求的成功或失败不会影响其他的请求。
---恢复内容结束---
---恢复内容开始---
(>>表示包含)
1.基本概念
Elasticsearch 是一个实时的分布式搜索分析引擎,用作全文检索,结构化搜索,分析及三个功能组合
tips:lucene具现化?
elasticsearch面向文档,意味着它存储整个对象或 文档。Elasticsearch索引每个文档内容使之可以被检索。Elasticsearch中,我们并不是对行列数据进行检索,而是对文档进行索引,检索,排序与过滤
使用json作为文档序列化的格式
将对象转化为json做索引,而不是将其存入表结构中进行检索
ex:
检索文档编辑
目前我们已经在 Elasticsearch 中存储了一些数据, 接下来就能专注于实现应用的业务需求了。第一个需求是可以检索到单个雇员的数据。
这在 Elasticsearch 中很简单。简单地执行 一个 HTTP GET 请求并指定文档的地址——索引库、类型和ID。 使用这三个信息可以返回原始的 JSON 文档:
GET /megacorp/employee/1
返回结果包含了文档的一些元数据,以及 _source 属性,内容是 John Smith 雇员的原始 JSON 文档:
{
"_index" : "megacorp",
"_type" : "employee",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
}
将 HTTP 命令由 PUT 改为 GET 可以用来检索文档,同样的,可以使用 DELETE 命令来删除文档,以及使用 HEAD 指令来检查文档是否存在。如果想更新已存在的文档,只需再次 PUT 。
索引>>类型>>文档>>属性
tips:类型?
索引:数据库
类型:表?
文档:记录
属性:字段类型
查询特色:相关性
2.集群相关
ex:
集群健康编辑
Elasticsearch 的集群监控信息中包含了许多的统计数据,其中最为重要的一项就是 集群健康 , 它在 status 字段中展示为 green 、 yellow 或者 red 。
GET /_cluster/health
在一个不包含任何索引的空集群中,它将会有一个类似于如下所示的返回内容:
{
"cluster_name": "elasticsearch",
"status": "green",
"timed_out": false, "number_of_nodes": 1, "number_of_data_nodes": 1, "active_primary_shards": 0, "active_shards": 0, "relocating_shards": 0, "initializing_shards": 0, "unassigned_shards": 0 }
status 字段指示着当前集群在总体上是否工作正常。它的三种颜色含义如下:
green- 所有的主分片和副本分片都正常运行。
yellow- 所有的主分片都正常运行,但不是所有的副本分片都正常运行。
red- 有主分片没能正常运行。
在本章节剩余的部分,我们将解释什么是 主 分片和 副本 分片,以及上面提到的这些颜色的实际意义。
每个节点都知道任意文档所在的位置,并能够将我们的请求直接转发到存储我们所需文档的节点。
索引是指向一个或多个物理分片的逻辑命名空间
tips:分片?
应用程序与索引直接交互而不与分片进行交互
一个副本分片只是一个主分片的拷贝。作为故障时保护数据的冗余备份,并为搜索和返回文档等读操作提供服务。
节点>>分片
分片是一个功能完整的搜索引擎,它拥有使用一个节点上所有资源的能力。
增加节点数目可以提高性能,单独增加副本分片并不能提高性能,但是可以提高数据冗余量。
ex:
增加节点变成

按照上面的节点配置,我们可以在失去2个节点的情况下不丢失任何数据。
“如果我们重新启动 Node 1 ,集群可以将缺失的副本分片再次进行分配,那么集群的状态也将如图 5 “将参数 number_of_replicas 调大到 2”所示。 如果 Node 1 依然拥有着之前的分片,它将尝试去重用它们,同时仅从主分片复制发生了修改的数据文件。”
note:此次启动之后主分片为哪个呢?
3.输入输出相关
一个 对象 是基于特定语言的内存的数据结构。 为了通过网络发送或者存储它,我们需要将它表示成某种标准的格式。JSON 是一种以人可读的文本表示对象的方法。 它已经变成 NoSQL 世界交换数据的事实标准。当一个对象被序列化成为 JSON,它被称为一个 JSON 文档 。
通常情况下,我们使用的术语对象和文档是可以互相替换的。 一个对象仅仅是类似于 hash 、 hashmap 、字典或者关联数组的 JSON 对象,对象中也可以嵌套其他的对象。 对象可能包含了另外一些对象。在 Elasticsearch 中,术语 文档 有着特定的含义。它是指最顶层或者根对象, 这个根对象被序列化成 JSON 并存储到 Elasticsearch 中,指定了唯一 ID。
文档元数据,三个必须的元数据元素:_index(索引),_type(类型),_id(标识)
索引名,这个名字必须小写,不能以下划线开头,不能包含逗号。
类型名,可以是大写或者小写,但是不能以下划线或者句号开头,不应该包含逗号, 并且长度限制为256个字符。
检索只有即时性
elasticsearch中文档是不可改变的,不能修改它们。当想要更新现有文档,需要重建索引或者进行替换,
更新过程:
- 从旧文档构建 JSON
- 更改该 JSON
- 删除旧文档
- 索引一个新文档、
创建新文档:
请记住, _index 、 _type 和 _id 的组合可以唯一标识一个文档。所以,确保创建一个新文档的最简单办法是,使用索引请求的 POST 形式让 Elasticsearch 自动生成唯一 _id :
POST /website/blog/
{ ... }
然而,如果已经有自己的 _id ,那么我们必须告诉 Elasticsearch ,只有在相同的 _index 、 _type 和 _id 不存在时才接受我们的索引请求。这里有两种方式,他们做的实际是相同的事情。使用哪种,取决于哪种使用起来更方便。
PUT /website/blog/123?op_type=create
{ ... }
第二种方法是在 URL 末端使用 /_create :
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 }
基本操作:PUT,DELETE操作是幂等的。所谓幂等是指不管进行多少次操作,结果都一样。比如我用PUT修改一篇文章,然后在做同样的操作,每次操作后的结果并没有不同,DELETE也是一样。POST是作用在一个集合资源之上的/articles),而PUT操作是作用在一个具体资源之上的(/articles/123)
hits
hits包含total字段表示匹配到的文档总数,并且一个hits数组包含所查询结果的前十个文档。
hits数组中每个结果包含文档的_index,_type,_id,加上_source字段
另外还有_score,它衡量文档与查询的匹配程度。默认情况优先返回最相关的文档结果,所以返回的文档是按照_score降序排列的。max_score值是与查询所匹配文档的_score的最大值。
took
took值表示执行搜索请求耗费了多少毫秒
shards
_shards部分告诉我们查询中参与分片的总数,以及成功数和失败数。
timeout
timed_out 值告诉我们查询是否超时。默认情况下,搜索请求不会超时。 如果低响应时间比完成结果更重要,你可以指定 timeout 为 10 或者 10ms(10毫秒),或者 1s(1秒):
GET /_search?timeout=10ms
在请求超时之前,Elasticsearch 将会返回已经成功从每个分片获取的结果。
note:
应当注意的是 timeout 不是停止执行查询,它仅仅是告知正在协调的节点返回到目前为止收集的结果并且关闭连接。在后台,其他的分片可能仍在执行查询即使是结果已经被发送了。
使用超时是因为 SLA(服务等级协议)对你是很重要的,而不是因为想去中止长时间运行的查询。
多索引,多类型
如果不对某一特殊的索引或者类型做限制,就会搜索集群中的所有文档。Elasticsearch 转发搜索请求到每一个主分片或者副本分片,汇集查询出的前10个结果,并且返回给我们。
然而,经常的情况下,你 想在一个或多个特殊的索引并且在一个或者多个特殊的类型中进行搜索。我们可以通过在URL中指定特殊的索引和类型达到这种效果,如下所示:
/_search- 在所有的索引中搜索所有的类型
/gb/_search- 在
gb索引中搜索所有的类型 /gb,us/_search- 在
gb和us索引中搜索所有的文档 /g*,u*/_search- 在任何以
g或者u开头的索引中搜索所有的类型 /gb/user/_search- 在
gb索引中搜索user类型 /gb,us/user,tweet/_search- 在
gb和us索引中搜索user和tweet类型 /_all/user,tweet/_search- 在所有的索引中搜索
user和tweet类型
当在单一的索引下进行搜索的时候,Elasticsearch 转发请求到索引的每个分片中,可以是主分片也可以是副本分片,然后从每个分片中收集结果。多索引搜索恰好也是用相同的方式工作的--只是会涉及到更多的分片。
分页
Elasticsearch 接受 from 和 size 参数:
size- 显示应该返回的结果数量,默认是
10 from- 显示应该跳过的初始结果数量,默认是
0
如果每页展示 5 条结果,可以用下面方式请求得到 1 到 3 页的结果:
GET /_search?size=5
GET /_search?size=5&from=5
GET /_search?size=5&from=10
考虑到分页过深以及一次请求太多结果的情况,结果集在返回之前先进行排序。 但请记住一个请求经常跨越多个分片,每个分片都产生自己的排序结果,这些结果需要进行集中排序以保证整体顺序是正确的。
轻量搜索
查询字符串搜索非常适用于通过命令行做即席查询。例如,查询在 tweet 类型中 tweet 字段包含 elasticsearch 单词的所有文档:
GET /_all/tweet/_search?q=tweet:elasticsearch
下一个查询在 name 字段中包含 john 并且在 tweet 字段中包含 mary 的文档。实际的查询就是这样
+name:john +tweet:mary
但是查询字符串参数所需要的 百分比编码 (译者注:URL编码)实际上更加难懂:
note:百分比编码:保留字符如":","/","?","&","=","@","%"等字符,转换成百分比编码表示时,用“%+对应的十六进制”来表示
GET /_search?q=%2Bname%3Ajohn+%2Btweet%3Amary
+ 前缀表示必须与查询条件匹配。类似地, - 前缀表示一定不与查询条件匹配。没有 + 或者 - 的所有其他条件都是可选的——匹配的越多,文档就越相关。
映射分析
通过请求 gb 索引中 tweet类型的_映射_(或模式定义),让我们看一看 Elasticsearch 是如何解释我们文档结构的:
GET /gb/_mapping/tweet
这将得到如下结果:
{
"gb": {
"mappings": {
"tweet": {
"properties": {
"date": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"name": {
"type": "string"
},
"tweet": {
"type": "string"
},
"user_id": {
"type": "long"
}
}
}
}
}
}
基于对字段类型的猜测, Elasticsearch 动态为我们产生了一个映射。
为了更好的进行查询工作,我们对文档的操作:分词与标准化
要对查询和文档进行相同的标准化!
分析器
将三个功能封装到一个包中:
字符过滤器:分词前整理字符串,一个字符过滤器可以刚掉html,或将&转化为’and‘
分词器:字符串被分词器分成单个词条。一个简单分词器遇到空格和标点时,可能会将文本拆分成词条
token过滤器:词条按照顺序通过token过滤器。这个过程可能会改变词条,删除词条,或增加词条。
分析器的应用场景
当我们 索引 一个文档,它的全文域被分析成词条以用来创建倒排索引。 但是,当我们在全文域 搜索 的时候,我们需要将查询字符串通过 相同的分析过程 ,以保证我们搜索的词条格式与索引中的词条格式一致。
全文查询,理解每个域是如何定义的,因此它们可以做 正确的事:
analyzed- 首先分析字符串,然后索引它。换句话说,以全文索引这个域。
not_analyzed- 索引这个域,所以它能够被搜索,但索引的是精确值。不会对它进行分析。
no- 不索引这个域。这个域不会被搜索到。
string 域 index 属性默认是 analyzed 。如果我们想映射这个字段为一个精确值,我们需要设置它为 not_analyzed :
{
"tag": {
"type": "string",
"index": "not_analyzed"
}
}
对于 analyzed 字符串域,用 analyzer 属性指定在搜索和索引时使用的分析器。默认, Elasticsearch 使用 standard 分析器, 但你可以指定一个内置的分析器替代它,例如 whitespace 、 simple 和 `english`:
{
"tweet": {
"type": "string",
"analyzer": "english"
}
}
在 自定义分析器 ,我们会展示怎样定义和使用自定义分析器。
尽管你可以 增加_ 一个存在的映射,你不能 _修改 存在的域映射。如果一个域的映射已经存在,那么该域的数据可能已经被索引。如果你意图修改这个域的映射,索引的数据可能会出错,不能被正常的搜索。

浙公网安备 33010602011771号