ELK学习笔记(二)之基础搜索(一)

5,533 阅读11分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第20天,点击查看活动详情

管理 Elasticsearch 索引和文档

在 es 中,索引和文档是 REST 接口操作的最基本资源,所以对索引和文档的 管理也是我们必须要知道的。索引一般是以索引名称出现在 REST 请求操作的资 源路径上,而文档是以文档 ID 为标识出现在资源路径上。映射类型_doc 也可以 认为是一种资源,但在 es7 中废除了映射类型,所以可以_doc 也视为一种接口。

索引的管理

在前面的学习中我们已经知道,GET 用来获取资源,PUT 用来更新资源, DELETE 用来删除资源。所以对索引,GET 用来查看索引,PUT 用来创建索引,DELETE 用来删除索引,还有一个 HEAD 请求,用来检验索引是否存在。除此之外,对索 引的管理还有

列出所有索引 GET /_cat/indices?v

image.png

关闭索引和打开

POST /open-soft/_close 除了删除索引,还可以选择关闭它们。如果关闭了一个索引,就无法通过 Elasticsearch 来读取和写人其中的数据,直到再次打开它。

在现实世界中,最好永久地保存应用日志,以防要查看很久之前的信息。另 一方面,在 Elasticsearch 中存放大量数据需要增加资源。对于这种使用案例,关 闭旧的索引非常有意义。你可能并不需要那些数据,但是也不想删除它们。

一旦索引被关闭,它在 Elasticsearch 内存中唯-的痕迹是其元数据,如名字 以及分片的位置。如果有足够的磁盘空间,而且也不确定是否需要在那个数据中 再次搜索,关闭索引要比删除索引更好。关闭它们会让你非常安心,永远可以重 新打开被关闭的索引,然后在其中再次搜索。

重新打开 POST /open-soft/_open

配置索引

通过 settings 参数配置索引,索引的所有配置项都以“index”开头。索引的 管理分为静态设置和动态设置两种。

静态设置

只能在索引创建时或在状态为 closed index(闭合索引)上设置,主要配置 索引主分片、压缩编码、路由等相关信息

index.number_of_shards 主分片数,默认为 5 , 只能在创建索引时设置,不能 修改

index.shard.check_on_startup 是否应在索引打开前检查分片是否损坏,当检查到分片损坏将禁止分片被打开。

  • false:默认值;
  • checksum:检查物理损坏;
  • true:检查物理和逻辑损坏,这将消耗大量内存和 CPU;
  • fix:检查物理和逻辑损坏。 有损坏的分片将被集群自动删除,这可能导致数据丢失

index.routing_partition_size 自定义路由值可以转发的目的分片数。默认为 1, 只能在索引创建时设置。此值必须小于 index.number_of_shards

index.codec 默认使用 LZ4 压缩方式存储数据,也可以设置为 best_compression,它使用 DEFLATE 方式以牺牲字段存储性能为代价来获得更高 的压缩比例。

如: 
put test1{
"settings":{
    "index.number_of_shards":3, "index.codec":"best_compression" 
    } 
}

动态设置

通过接口_settings进行,同时查询配置也通过这个接口进行,比如:

  • get _settings
  • get /open-soft/_settings
  • get /open-soft,test1/_settings

配置索引则通过以下命令,比如 修改test1 的往磁盘刷新数据的频率:

put test1/_settings { "refresh_interval":"2s" }

常用的配置参数如下:

  • index.number_of_replicas 每个主分片的副本数。默认为 1
  • index.auto_expand_replicas 基于可用节点的数量自动分配副本数量,默认为 false(即禁用此功能)
  • index.refresh_interval 执行刷新操作的频率。默认为 1s。可以设置为 -1 以 禁用刷新。
  • index.max_result_window 用于索引搜索的 from+size 的最大值。默认为 10000
  • index.blocks.read_only 设置为 true 使索引和索引元数据为只读,false 为 允许写入和元数据更改。
  • index.blocks.read 设置为 true 可禁用对索引的读取操作
  • index.blocks.write 设置为 true 可禁用对索引的写入操作
  • index.blocks.metadata 设置为 true 可禁用索引元数据的读取和写入
  • index.max_refresh_listeners 索引的每个分片上可用的最大刷新侦听器数
  • index.max_docvalue_fields_search 一次查询最多包含开启 doc_values 字段 的个数,默认为 100
  • index.max_script_fields 查询中允许的最大 script_fields 数量。默认为 32。
  • index.max_terms_count 可以在 terms 查询中使用的术语的最大数量。默认 为 65536。
  • index.routing.allocation.enable 控制索引分片分配。All(所有分片)、primaries (主分片)、new_primaries(新创建分片)、none(不分片)
  • index.routing.rebalance.enable 索引的分片重新平衡机制。all、primaries、 replicas、none
  • index.gc_deletes 文档删除后(删除后版本号)还可以存活的周期,默认 为 60s
  • index.max_regex_length 用于正在表达式查询(regex query)正在表达式长度, 默认为 1000

配置映射

通过_mapping 接口进行,在我们前面的章节中,已经展示过了。get /open-soft/_mapping

或者只看某个字段的属性: get /open-soft/_mapping/field/lang

修改映射,当然就是通过 put 或者 post 方法了。但是要注意,已经存在的 映射只能添加字段或者字段的多类型。但是字段创建后就不能删除,大多数参数 也不能修改,可以改的是 ignore_above。所以设计索引时要做好规划,至少初始 时的必要字段要规划好。

文档的管理

增加文档

增加文档,我们在前面的内容已经知道了,比如:

image.png

如果增加文档时,在 Elasticsearch 中如果有相同 ID 的文档存在,则更新此文 档,比如执行

image.png 则会发现已有文档的内容被更新了。

文档的 id

当创建文档的时候,如果不指定 ID,系统会自动创建 ID。自动生成的 ID 是 一个不会重复的随机数。使用 GUID 算法,可以保证在分布式环境下,不同节点 同一时间创建的_id 一定是不冲突的。比如:

image.png

查询文档

get /open-soft/_doc/1

更新文档

前面我们用 put 方法更新了已经存在的文档,但是可以看见他是整体更新文档,如果我们要更新文档中的某个字段怎么办?需要使用_update 接口。

post /open-soft/_update/1/ 
{ 
"doc":{
    "year": 2016 
  } 
}

如果文档中存在 year 字段,更新 year 字段的值,如果不存在 year 字段,则会新增 year 字段,并将值设为 2016。 update 接口在文档不存在时提示错误,如果希望在文档不存在时创建文档, 则可以在请求中添加 upsert 参数,例如:

image.png

或:

image.png

upsert 参数定义了创建新文档使用的文档内容,而 doc_as_upsert 参数的含 义是直接使用 doc 参数中的内容作为创建文档时使用的文档内容。

删除文档

delete /open-soft/_doc/1

数据检索和分析

为了方便我们学习,我们导入 kibana 为我们提供的范例数据。

image.png

image.png

添加完成,进行查询索引

image.png

目前为止,我们已经探索了如何将数据放入 Elasticsearch, 现在来讨论下如何将数据从 Elasticsearch 中拿出来,那就是通过搜索。毕竟,如果不能搜索数据, 那么将其放入搜索引擎的意义又何在呢?幸运的是,Elasticsearch 提供了丰富的 接口来搜索数据,涵盖了 Lucene 所有的搜索功能。因为 Elasticsearch 允许构建 搜索请求的格式很灵活,请求的构建有无限的可能性。要了解哪些查询和过滤器 的组合适用于你的数据,最佳的方式就是进行实验,因此不要害怕在项目的数据上尝试这些组合,这样才能弄清哪些更适合你的需求。

_search 接口

所有的 REST 搜索请求使用_search 接口,既可以是 GET 请求,也可以是 POST 请求,也可以通过在搜索 URL 中指定索引来限制范围。

_search 接口有两种请求方法,一种是基于 URI 的请求方式,另一种是基于 请求体的方式,无论哪种,他们执行的语法都是基于 DSL(ES 为我们定义的查询 语言,基于 JSON 的查询语言),只是形式上不同。我们会基于请求体的方式来 学习。比如说:

get kibana_sample_data_flights/_search { "query":{ "match_all":{} } }

get kibana_sample_data_flights/_search { "query":{ "match_none":{} } }

image.png

当然上面的查询没什么太多的用处,因为他们分别代表匹配所有和全部匹配。

所以我们经常要使用各种语法来进行查询,一旦选择了要搜索的索引,就需 要配置搜索请求中最为重要的模块。这些模块涉及文档返回的数量,选择最佳的 文档返回,以及配置不希望哪些文档出现在结果中等等。

  • query 这是搜索请求中最重要的组成部分,它配置了基于评分返回的最 佳文档,也包括了你不希望返回哪些文档。
  • size 代表了返回文档的数量。
  • from 和 size 一起使用,from 用于分页操作。需要注意的是,为了确定 第 2 页的 10 项结果,Elasticsearch 必须要计算前 20 个结果。如果结果集合不断 增加,获取某些靠后的翻页将会成为代价高昂的操作。
  • _source 指定_ source 字段如何返回。默认是返回完整的_ source 字段。 通过配置_ source,将过滤返回的字段。如果索引的文档很大,而且无须结果中的 全部内容,就使用这个功能。请注意,如果想使用它,就不能在索引映射中关闭 _ source 字段。
  • sort 默认的排序是基于文档的得分。如果并不关心得分,或者期望许多 文档的得分相同,添加额外的 sort 将帮助你控制哪些文档被返回

结果起始和页面大小

命名适宜的 from 和 size 字段,用于指定结果的开始点,以及每“页"结果的 数量。举个例子,如果发送的 from 值是 7,size 值是 5,那么 Elasticsearch 将返回 第 8、9、10、 11 和 12 项结果(由于 from 参数是从 0 开始,指定 7 就是从第 8 项结果开始)。如果没有发送这两个参数,Elasticsearch 默认从第一项结果开始 ( 第 0 项结果),在回复中返回 10 项结果。例如:

image.png

但是注意,from 与 size 的和不能超过 index. max_result_window 这个索引配 置项设置的值。默认情况下这个配置项的值为 10000,所以如果要查询 10000 条以 后的文档,就必须要增加这个配置值。例如,要检索第 10000 条开始的 200 条数 据,这个参数的值必须要大于 10200,否则将会抛出类似“ Result window is too large'的异常。

由此可见,Elasticsearch 在使用 from 和 size 处理分页问题时会将所有数据 全部取出来,然后再截取用户指定范围的数据返回。所以在查询非常靠后的数据 时,即使使用了 from 和 size 定义的分页机制依然有内存溢出的可能,而 max_ result_ window 设置的 10000 条则是对 Elastiesearch 的一.种保护机制。

那么 Elasticsearch 为什么要这么设计呢?首先,在互联网时代的数据检索应 该通过相似度算法,提高检索结果与用户期望的符和度,而不应该让用户在检索 结果中自己挑选满意的数据。以互联网搜索为例,用户在浏览搜索结果时很少会 看到第 3 页以后的内容。假如用户在翻到第 10000 条数据时还没有找到需要的结 果,那么他对这个搜索引擎一定会非常失望。

_source 参数

元字段_source 中存储了文档的原始数据。如果请求中没有指定_source, Elasticsearch 默认返回整个_ source, 或者如果_ source 没有存储,那么就只返 回匹配文档的元数据:_ id、_type、_index 和_score 例如:

image.png

你不仅可以返回字段列表,还可以指定通配符。例如,如果想同时返回" DestCountry "和" DestWeather "字段,可以这样配置_ source: "Dest*"。 也可以使 用通配字符串的数组来指定多个通配符,例如_ source:[" Origin*", "* Weather "]。

image.png

不仅可以指定哪些字段需要返回,还可以指定哪些字段无须返回。比如:

image.png

排序

大多搜索最后涉及的元素都是结果的排序( sort )。如果没有指定 sort 排序选 项,Elasticsearch 返回匹配的文档的时候,按照_ score 取值的降序来排列,这样 最为相关的(得分最高的)文档就会排名在前。为了对字段进行升序或降序排列,指定映射的数组,而不是字段的数组。通过在 sort 中指定字段列表或者是字段映 射,可以在任意数量的字段上进行排序。例如:

image.png

主要参考:享学课堂Mark老师