第一章 Elasticsearch入门
1.1Elasticsearch是什么
1.2全文搜索
Lucene倒排索引
1.3基础知识
1.3.1 Elasticsearch术语及概念
索引词term:能够被索引的精确值,索引词可以通过term查询进行准确搜索
文本text:一段普通的非结构化文字,通常文本会被分析成一个个的索引词
分析analysis:将文本转换为索引词的过程,依赖于分词器
集群cluster:一个或多个节点组成,对外提供服务;
节点node: 一个节点是一个逻辑上独立的服务,它是集群的一部分,可以存储数据
路由routing:确定文档存储于哪个主分片中
分片shard:分片是单个lucene实例,每个分片是一个全功能的、独立的单元,可以托管在集群中的任何节点
主分片primary shard:默认一个索引有5个主分片,索引一但建立,分片数量不能修改;副分片replica shard:主分片的复制,增加高可用性、提高性能、允许水平扩展、允许并行操作,查询可以在主分片或者副本分片中进行,默认一个主分片会有一个副本分片,但是可 以动态设置,但副本分片必须部署在不同的节点上,不能部署于和主分片相同的节点上
复制replica:可以实现故障转移,保证系统高可用, 每个分片的副本
一个索引被分成5个分片, 通过路由分发数据, 每个分片可以有多个副本, 同时提供服务, 提供并发和高可用
索引index:具有相同结构的文档集合
类型type:在索引中,可以定义一个或者多个类型,类型是索引的逻辑分区
文档document:一条记录,json格式的字符串。原始的json文档被存储在_source字段中
映射mapping:类似于表结构,定义每个索引中每一个字段类型,可以事先定义或者第一次存储时自动识别
字段field:每个字段都有字段类型,如整数、字符串等,字段还可以指定如何时分析该字段的值
来源字段source field:存储原始对象,不显示索引分析后的其他任何数据 _source字段
主键ID:一个文件的唯一标识,文档的index/type/id必须唯一
1.4安装配置
1.5对外接口
1.5.1 API约定
- 多索引参数
_all表示全部索引,另外,也支持使用通配符,如*,同时也支持排除操作,+test*,-test3表示查询所有以test开头的索引,但排除test3
多索引查询还支持这些参数:ignore_unavailable当索引不存在或关闭时,是否忽略,值为true/false;allow_no_indices当有索引不存在时,是否返回查询失败,值为true/false;expand_wildcards控制通配符匹配范围,open只作用于开启状态的索引,close只作用于关闭状态的索引,none不可用,all同时支持open和close
日期筛选
语法:<static_name{date_math_expr{date_format|time_zone}}>
<索引名{动态日期计算表达式{日期格式|时区,默认UTC}}>
curl -XGET ‘127.0.0.1:9200/<logstash-{now/d-2d}>/_search’ {“query”:{…}}
日期计算表达:假如当前为2018.04.10
<logstash-{now/d}> 为logstash-2018.04.10
<logstash-{now/M}> 为logstash-2018.04.01
<logstash-{now/M{YYYY.MM}}> 为logstash-2018.04
<logstash-{now/M-1M{YYYY.MM}}> 为logstash-2018.03
<logstash-{now/d{YYYY.MM.dd|+08:00}}> 为logstash-2018.04.10
如果索引名包含{}可以通过添加\转义,如<elastic\{ON\}-{now/M}>会被转义为elastic{ON}-2018.04.10
可以用逗号选择多个时间,如选择最近三天可以这样写
curl -XGET ‘127.0.0.1:9200/<logstash-{now/d-2d}>,<logstash-{now/d-d}>,<logstash-{now/d}>/_search’ {“query”:{…}}
通用参数
pretty格式化后的json方便阅读?pretty=true 还可以输出为yaml格式 ?format=yaml
human对于统计数据,支持适合阅读的单位,会消耗更多资源,默认false 使用?human=true
日期表达式,格式化日期表达式,范围查询gt大于和lt小于,或者在日期聚合中用from to表达时间范围
表达式设定的日期为now或者日期字符串加||
+1h 增加一小时
-1D 减少一小时
/D上一个小时
支持单位:年y、月M、周w、日d、小时h、分m、秒s
now+1h当前时间加一小时,以毫秒为单位
now+1h+1m当前时间加一小时一分钟,以毫秒为各单位
now+1h/d当前时间加一小时,四舍五入到最近一天
2018-01-01||+1M/d 2018-01-01加一个月,向下舍入到最近一天
响应过滤
filter_path
选择返回字段,逗号分割,可以使用*
两个通配符**匹配不确定名称的字段
curl -XGET ‘127.0.0.1:9200/_search?pretty&filter_path=took,hits.hits._id,hits._score’
curl -XGET ‘127.0.0.1:9200/_search?pretty&filter_path=hits.hits._source&_source=title’
flat_settings紧凑参数,为true时更加紧凑
增删改查
1.5.4创建库
JAVA API调用
….
参考sgg的教程
第二章 索引
索引是具有相同结构的文档集合
2.1索引管理
创建索引
创建索引的时候可以通过修改number_of_shards和number_of_replicas来设置分片和副本的数量。默认分片为5,副本为1,副本数可以设置为0
请求 PUT {host}secisland/
{
“settings”: {
“index”: {
“number_of_shards”: 3,
“number_of_replicas”: 2
}
}
}
设置分片数为3,副本数为2
简写
{
“settings”: {
“number_of_shards”: 3,
“number_of_replicas”: 0
}
}
对副本数的修改可以使用update-index-settings API实现
PUT secisland/_settings/
{
“number_of_replicas”: 2
}
文档字段都要有数据类型,默认可以自动识别,也可以使用mappings参数显式映射
创建自定义类型
PUT secisland/
{
“settings”: {
“number_of_shards”: 3,
“number_of_replicas”: 2
},
“mappings”: {
“secilog”: {
“properties”: {
“logType”: {
“type”: “string”,
“index”: “not_analyzed”
}
}
}
}
}
创建一个名号secilog的类型,类型中有一个字段logType,字段类型为string,不对这个字段分析
删除索引
DELETE secisland/
删除索引需要指定索引名、别名或者通配符
删除多个可用逗号分隔,使用_all或*删除全部索引
配置文件中设置action.destructive_requires_name为true可以禁止通配符或_all删除索引
获取索引
从一个或者多个索引中获取信息
GET secisland/
获取索引需要指定索引名称,别名或者通配符返回结果过滤:
自定义返回结果的属性, 上面的返回全部信息, 这里只返回想要的信息
GET */_settings,_mappings 仅获取_settings和_mappings属性
打开/关闭索引
关闭的索引只能显示索引元数据,不能进行数据读写操作
POST /索引名/_close
POST /索引名/_open
可以同时打开或关闭多个索引,全部使用_all或*,
如果包含不存在的索引则抛出异常,使用ignore_unavailable=true可以不显示异常
配置文件设置action.destructive_requires_name为true禁止使用通配符和_all
禁止使用关闭索引功能settingscluster.indices.close.enable为false
2.2索引映射管理
增加映射
可以向索引添加文档类型type或者向文档类型type中添加字段field
PUT secisland/
{
“mappings”: {
“log”: {
“properties”: {
“message”: {
“type”: “string”
}
}
}
}
}
新建索引并设置文档类型为log,其中包含字段message类型为string
多个索引设置映射
一次向多个索引添加文档类型
PUT {index}/_mapping/{type}
{body}
{index}可以使用逗号分割,支持通配符和*和_all
更新字段映射
一般情况下,现在字段映射不会更新,但有些例外
新的属性被添加到对象数据类型的字段
新的多域字段被添加到现有字段
doc_values可以被禁用
增加ignore_above参数
PUT secisland/_mapping/user
{
“mappings”: {
“user”: {
“properties”: {
“name”: {
“properties”: {
“first”: {
“type”: “string”
}
}
},
“user_id”: {
“type”: “string”,
“index”: “not_analyzed”,
“ignore_above”: 100
}
}
}
}
}
可以增加name的子字段,可以添加"ignore_above":100
不同类型之间的冲突
同一索引内,可以有多个类型,但是不同类型的同名字段映射是相同的,因为它们内部在同一领域内。更新时会抛出异常,除非在更新时指定update_all_types参数,此时将更所所有同名字段
获取映射
允许通过索引或者索引和类型来搜索
GET secisland/_mapping/type_one
GET secisland/_mapping
系统支持同时获取多个索引和类型
{index}/_mapping/{type} {index}{type}均可用逗号分割,可使用通配符和_all
_all/_mapping和_mapping等价
获取字段映射
格式为:{index}/{type}/_mapping/field/{field} 倒数第二个field为固定关键字
其中{index}{type}{field}可以逗号分割,通配符和_all
GET secisland/type_two/_mapping/field/text
如果包含Object类型字段,可能会产生重名, 使用对象.属性方式
判断类型是否存在
HEAD secisland/type_one 存在返回200,不存在返回404
2.3 索引别名
可以对别名编写过滤器或者路由,别名不能重复,也不能和索引名重复。别名类似于数据库中的视图
添加别名
POST _aliases
{
“actions”: [
{
“add”: {
“index”: “secisland”,
“alias”: “alias1”
}
}
]
}
删除别名
POST _aliases
{
“actions”: [
{
“remove”: {
“index”: “secisland”,
“alias”: “alias1”
}
}
]
}
别名没有修改的语法,只能先删除再增加,如
{
“actions”: [
{
“remove”: {
“index”: “secisland”,
“alias”: “alias1”
}
},
{
“add”: {
“index”: “secisland”,
“alias”: “new_alias”
}
}
]
}
同时设置多个索引的别名
POST_aliases {“actions”:[{“add”:{“indices”:[“secisland”,“logstash*”],“alias”:“new_alias”}}]}
通配符指定的索引只在当前索引生效,后续添加索引不会被自动添加到别名上。对某一别名做索引时,如果该别名关联多个索引会报错
过滤索引别名
创建过滤别名:
通过参数添加别名
添加一个别名
删除别名
语法:DELETE {index}/_alias/{name}
查询现有别名
可通过索引或别名进行查询
语法:GET {index}/_alias/{alias} ignore_unavailable设置为true将忽略不存在的索引
2.4 索引配置
有些参数是可以在建好索引之后进行修改的
更新索引配置
/_settings 针对所有索引
{index}/_settings 针对特定的索引设置副本数
PUT secisland/_settings {“index”:{“number_of_replicas”:4}}
更新分词器
POST secisland/_close
PUTsecisland/_settings
{
“analysis”: {
“analyzer”: {
“content”: {
“type”: “custom”,
“tokenizer”: “whitespace”
}
}
}
}
POST secisland/_open
获取配置
GET secisland/settings
GET secisland/settings/name=index.number* 只返回index.number*的配置
Number_of_replicas和number_of_shards
索引分析( analysis)是这样一个过程:首先,把一个文本块分析成一个个单独的词( term),为了后面的倒排索引做准备。然后标准化这些词为标准形式,提高它们的“可搜索性”。这些工作是分析器( analyzers)完成的。一个分析器( analyzers)是一个组合,用于将三个功能放到一起:
- 字符过滤器:字符串经过字符过滤器( character filter)处理,它们的工作是在标记化之前处理字符串。字符过滤器能够去除HTML标记,或者转换“&”为“and”。
2.分词器:分词器( tokenizer)被标记化成独立的词。一个简单的分词器( tokenizer)可以根据空格或逗号将单词分开。
3.标记过滤器:每个词都通过所有标记过滤( token filters)处理,它可以修改词(例如将"Quick"转为小写),去掉词(例如连接词像“a”、“ and”、“ the”等),或者增加词(例如同义词像“jump”和“leap”)。
Elasticsearch提供很多内置的字符过滤器,分词器和标记过滤器。这些可以组合起来创建自定义的分析器以应对不同的需求
索引模板
创建索引模板
模板包括索引的参数设置settings和映射mapping,在创建新索引的时候指定模板名称就可以使用模板定义好的参数设置和映射
PUT_template/template_1
{
“template”: “te*”,
“settings”: {
“number_of_shards”: 1
},
“mappings”: {
“type1”: {
“_source”: {
“enabled”: false
}
}
}
}
重建索引
重建索引最基本的功能是拷贝文件从一个索引到另一个索引
2.5索引监控
包括索引的统计信息、碎片信息、恢复状态、分片信息
索引统计
提供索引中不同内容的统计数据,其中大多数统计数据也可以从节点级别范围取得
获取所有聚合以及索引的统计数据
GET _stats
GET /secisland/_stats
默认返回所有信息,也可以指定返回特定数据,选项有:
一些统计数据可以作用在字段粒度上,接受逗号分隔的字段列表
fields 包含统计数据中的字段列表,默认列表
completion_fields 包含完成建议统计数据中的字段列表
fielddata_fields 包含在字段数据统计数据中的字段列表
如:
#获取所有索引的混合和刷新统计数据
GET _stats/merge,refresh
#获取名为secisland索引中类型为type1和type2的文档统计数据
GET secisland/_stats/indexing?types=type1,type2
#获取分组group1和group2的搜索统计数据
GET _stats/search?groups=group1,group2返回的统计数据在索引级别发生聚合,生成名为primaries和total的聚合,其中primaries仅包含主分片的值,total是主分片和从分片的累计值
为了获取分片级别的统计数据,需要设置level参数为shards
当分片在集群中移动的时候,它们的统计数据会被清除,视作它在其他节点中被创建
即使分片“离开”一个节点,那个节点仍然会保存分片之前的统计数据
索引分片
提供lucene索引所在的分片信息。用来提供分片和索引的更多统计信息,可能是优化信息,删除的’垃圾’数据等
GET /secisland/_segments
GET /secisland,secisland2/_segments
GET _segments
索引恢复
提供正在进行恢复的索引分片信息,可以报告指定索引或者集群范围的恢复状态
GET secisland,secisland2/_recovery
GET _recovery?pretty&human
选项列表
detailed 显示详细的视图。主要用来查看物理索引文件的恢复,默认为false
active_only 显示正在进行的恢复,默认为false
索引分片存储
提供索引分片副本的存储信息。报告分片副本存在的节点、分片副本版本、指示分片副本最近的状态以及在开启分片索引时遭遇的任何异常
GET /secisland/_shard_stores
GET /secisland,secisland2/_shard_stores
GET /_shard_stores
列出存储信息的分片范围可以通过status参数进行修改。默认是yellow和red,使用green列出所有信息
GET _shard_stores?status=green
2.6 状态管理
包括清除索引缓存、索引刷新、冲洗索引、合并索引接口等
清除缓存
清除所有缓存或者关联一个或者更多索引的特定缓存
POST secisland/_cache/clear
明确清理所有缓存,可以明确设置query、fielddata和request来清理特定缓存
索引刷新
明确的刷新一个或多个索引,使之前最后一次刷新之后的所有操作被执行
POST secisland/_refresh
POST secisland,test/_refresh
操作一个或多个索引
冲洗
通过执行冲洗将数据保存到索引存储并且清除内部事务日志,以此来释放索引的内存空间
es通过使用内存启发式算发来自动触发冲洗操作
POST secisland/_flush
合并索引
强制合并一个或更多索引。合并分片数量和每个分片保存的lucene索引,强制合并可以通过合并来减少分片数量
调用会被阻塞直到合并完成,如果http连接丢失,请求会在后台继续执行,任何新的请求都会被阻塞直到前一个强制合并完成
POST secisland/_forcemerge
POST secisland/_forcemerge?max_num_segments=1
参数:
max_num_segments 用于合并的分片数量,为充分合并,设置它的值为1
only_expunge_deletes 合并过程是否只删除分片中被删除的文档。lucene中,文档不会从分片中删除,只是标记为删除,通过执行合并,可以删除这些标记为删除的文档,默认值为false
flush 强制合并之后是否执行冲洗,默认为true
2.7文档管理
关系型数据库中的记录
增加文档
如果有相同id的文档,则更新此文档
PUT secisland/secilog/1
{
“collect_type”: “syslog”,
“collect_date”: “2016-01-11T09:32:12”,
“message”: “Failed to login”
}
返回:
{
“_index”: “secisland”,
“_type”: “secilog”,
“_id”: “1”,
“_version”: 2,
“_shards”: {
“total”: 2,
“successful”: 1,
“failed”: 0
},
“created”: false
}
其中total表示文档被创建的时候,在多少分片中进行操作,包括主分片和副本分片,所以这里为2,因为包括一个副本分片
1 、自动创建索引
创建文档的时候,如果索引不存在,会自动创建索引。自动创建的索引会自动映射每个字段的类型
可以在配置文件中设置action.auto_create_index为false禁用自动创建索引
自动创建索引可以通过模板设置索引名称,如可以设置action.auto_create_index为+aaa* -bbb* +ccc* -* (+为准许,-为禁止)
2 、版本号
每个文档都有一个版本号_version,通过版本号可以达到并发控制的效果,在操作文档的过程中指定版本号,哪果和版本号不一致时操作会被拒绝
版本号常用在对事务的处理中
PUT secisland/secilog/1?version=4 {“message”:“Failed to loginSSSS”} 当指定的版本号不是最新的时,会更新失败
版本号是实时更新的,不存在缓存现象,操作时不指定版本号,则系统不对版本号进行一致性检查
版本号可以从外部获取,当使用外部版本号时,操作文档时会对比参数中版本号是否大于文档中版本号,只有大于时才执行操作
3 、操作类型
通过op_type=create参数强制执行创建操作, 不会执行更新操作, 如果存在则抛出异常
PUT secisland/secilog/1?op_type=create {“message”:“Failed to loginSSMSS”}
另一个写法是
PUT secisland/secilog/1/_create {“message”:“Failed to loginSSMSS”}
4、自动创建ID
当创建文档时,不指定ID,系统会自动创建ID。自动生成的ID是一个20位随机数
POST secisland/secilog/?op_type=create {“message”:“Failed to loginSSMSS”}
POST secisland/secilog/ {“message”:“Failed to loginSSMSS”}
Id包含在返回值中的_id字段中
5、分片选择
默认分片的选择是通过id的散列值进行控制
可以使用router来使用指定参数的哈希而不是id的哈希
POST secisland/secilog/?routing=lily
{
“message”: “Failed to loginSSMSS”
}
这将由lily的哈希值来确定
6、其它说明
分布式 索引操作只针对主节点的分片进行,再分发到副本分片中
一致性 为防止当网络出现问题时写入不一致,只有在有效节点数量大于一定数量时生效[总结点数/2+1],该值可以通过action.write_consistency参数设置
刷新 更新的时候可以指定refresh为true立即刷新,系统做了充分的优化,不会对系统产生任何影响,需要注意的是查询操作refresh操作没有意义
空操作 当文档内容没有任何改变时,更新操作也会生效,仅体现为版本号的变化,可以指定detect_noop为true解决该问题,该参数在创建索引的时候无效
超时 默认为1分钟,可以通过设置timeout修改,如timeout=5m
更新删除文档
可以通过脚本操作来更新文档。更新操作从索引中获取文档,再执行脚本,最后获得返回结果。它使用版本号控制文档获取或者重建索引
更新操作是完全重新索引文件
PUT secisland/secilog/1 {“counter”:1,“tags”:[“red”]}
1、脚本开启功能
基于安全考虑,默认是禁用动态脚本的。如果需要开启,在配置文件中添加以下代码:
script.inline: on
script.indexed: on
script.file: on
配置后需要重启es
2、用脚本更新文档
POST secisland/secilog/1/_update
{“script”:{“inline”:“ctx._source.counter += count”,“params”:{“count”:4}}}
POST secisland/secilog/1/_update
{“script”:{“inline”:“ctx._source.tags += tag”,“params”:{“tag”:“blue”}}}
在脚本中,除了_source外,其它内置参数也可以使用,如_index、_type、_version、_routing、_parent、_timestamp、_ttl等
POST secisland/secilog/1/_update {“script”:“ctx._source.name_of_new_field = “value_of_new_field””} #添加新字段
POSTsecisland/secilog/1/_update {“script”:“ctx._source.remove(“name_of_new_field”)”} #删除一个字段
#条件判断,删除tags字段包含blue的文档
{“script”:{“inline”:“ctx._source.tags.contains(tag) ? ctx.op=“delete” : ctx.op=“none””,“params”:{“tag”:“blue”}}}
部分文档更新:
将文档合并到现有文档中,简单的递归合并、对象内部合并、替换核心的键值和数组
POST secisland/secilog/1/_update {“doc”:{“name”:“new_name”}} #新增字段name
当新文档和老文档不一致时,会重新建立索引,可以通过detect_noop为false设置为任何时候都重新建立索引
POST secisland/secilog/1/ {“doc”:{“name”:“new_name”},“detect_noop”:false}
删除文档
DELETE secisland/secilog/1/
查询文档
通过文档ID查询具体的某一个文档
GET secisland/secilog/1/
GET secisland/_all/1/ #type字段可以设置为_all
默认的,查询获得的数据是实时的,且不受索引刷新率影响。禁用实时性,可以将参数realtime设置为false,或者全局设置action.get.realtime为false
GET secisland/secilog/1?_source=false #不返回_source字段
#过滤_source中的部分字段
当需要返回多个字段时,可以使用逗号或者*
GET secisland/secilog/1?_source_include=doc
GET secisland/secilog/1?_source_exclude=doc使用fields字段,可以查询一组字段,返回字段是数组类型的
GET secisland/secilog/1?fields=year,sex
如果建立索引后还没来得及刷新,查询得到的内容是事务的日志
但有些字段只有在索引的时候才会产生,当访问时,会抛出异常,可以通过设置ignore_errors_on_generated_fields=true来忽略异常
1、只获取文档内容
{index}/{type}/{id}/_source
GET secisland/secilog/1/_source
2、分片选择
在查询的时候指定路由routing,当路由不存在时,返回空值
GET secisland/secilog/1?routing=secisland
3、查询参数
通过参数,可以指定查询在主节点上还是副本节点上执行
_primary 在主节点上
_local 尽可能在本地节点上进行
refresh 可设置为true,使之在搜索操作前刷新相关分片保证可以及时查询到,但会消耗系统资源,如非必要勿开启
多文档操作
多文档查询bulk
1、多文档查询
可以分别指定index、type、id来进行多个文档的查询。返回查询到的文档数组
POST _mget
{“docs”:[{“_index”:“secisland”,“_type”:“secilog”,“_id”:“1”},{“_index”:“secisland”,“_type”:“secilog”,“_id”:“2”}]}
在查询的时候,index、type可以在URL中直接写
POST secisland/secilog/_mget {“docs”:[{“_id”:“1”},{“_id”:“2”}]}
POST secisland/secilog/_mget {“ids”:[“1”,“2”]}
2、type参数说明
_type允许为空,当设置为空或者_all的时候,系统会匹配第一个查询到的结果
如果不设置_type,当有许多文件有相同的_id的时候,系统最终得到的只有第一个匹配的文档
默认,_source字段将在每个文档中返回,可以使用_source、_source_include、_source_exclude进行过滤
POST secisland/secilog/_mget
{“docs”:[{“_id”:“1”,“_source”:false},{“_id”:“2”,“_source”:[“collect_type”,“collect_date”]}]}
3、块操作
可以在一个接口中处理文档内容,包括创建、删除和修改,块操作可以提高系统效率【?】
POST _bulk
{“index”:{“_index”:“secisland”,“_type”:“secilog”,“_id”:“10”}}
{“field1”:“value1”}
{“index”:{“_index”:“secisland”,“_type”:“secilog”,“_id”:“13”}}
{“field1”:“value3”}
{“delete”:{“_index”:“secisland”,“_type”:“secilog”,“_id”:“12”}}
和批量查询类似,_bulk、{index}/_bulk、{index}/{type}/_bulk三种方式都可以执行
索引词频率
term vector是lucene中的概念,就是对于文档中的某一列,如title、body这种文本类型的建立词频的多维向量空间,每一个词就是一个维度,这个维度的值就是这个词在这个列中的频率
es中termvectors返回在索引中特定文档的统计信息,是实时分析的,如果不想实时分析,可以设置realtime参数为false
默认情况下,索引词频率统计是关闭的,需要在建立索引的时候手工打开
第三章 映射
3.1映射
映射是定义存储和索引的文档类型以及字段的过程。即定义每个字段的数据类型。
概念
1、映射类型
每个索引有一个或多个映射类型,用来在索引中将文档划分为不同的逻辑组
元字段:定义如何处理文档无数据,包括_index字段、_type字段、_id字段、_source字段
字段或属性:同一索引中不同映射类型的相同名称字段必须拥有相同的映射
2、字段数据类型
简单数据类型:字符串string、日期date、长整型long、双精度浮点型double、布尔型boolean、IP、integer
JSON的层次性类型:对象object、嵌套nested、地理点geo_point、地理形状geo_shape
一个数据类型通过fields参数支持多字段
3、动态映射
字段的映射类型在使用前不需要事先定义
动态映射可以配置自定义映射用于新类型或者新字段
4、显式映射
相对于动态映射,显示指定
5、更新当前映射
除了记录之外,现有的映射类型和字段不能更新,修改映射意味着放弃已经索引的文档,好的做法是根据映射创建新的索引并且重新索引数据
6、映射类型之间共享字段
映射类型在每个索引中是唯一的,一个索引中不同type中只要是同名的field则映射类型相同,但参数可以不同,如copy_to参数、dynamic参数、enabled参数、ignore_above参数、include_in_all参数
当产生类型冲突时,可以选择使用更详细的命名
如titile改为user_title
7、映射示例
PUT secisland
{
“mappings”: {
“user”: {
“_all”: {
“enabled”: false
},
“properties”: {
“title”: {
“type”: “string”
},
“name”: {
“type”: “string”
},
“age”: {
“type”: “integer”
}
}
},
“blogpost”: {
“properties”: {
“title”: {
“type”: “string”
},
“body”: {
“type”: “string”
},
“user_id”: {
“type”: “string”,
“index”: “not_analyzed”
},
“created”: {
“type”: “date”,
“format”: “strict_date_optional_time||epoch_millis”
}
}
}
}
}
user映射类型取消元字段_all
3.2字段数据类型
分为核心数据、复杂数据、地理数据、专门数据
核心数据类型
字符串:string
数字:long、integer、short、byte、double、float
日期:date
布尔:boolean
二进制:binary
复杂数据类型
数组:不需要专门的类型来定义数组
对象:object,单独的JSON对象
嵌套:nested,关于JSON对象的数组
地理数据类型
地理点:geo_point,经纬点
地理形状:geo_shape,多边形复杂地理形状
专门数据类型
IPv4:IP
完成数据:completion,提供自动补全的建议
单词计数:token_count,统计字符串中的单词数量
核心数据类型
字符串
分为两种情况
全文本:可以分词,不用于排序且很少用于聚合
关键字:精准值,常用于过滤、排序、参与聚合。不参与分词
PUT secisland
{
“mappings”: {
“secilog”: {
“properties”: {
“full_name”: {
“type”: “string”
},
“status”: {
“type”: “string”,
“index”: “not_analyzed”
}
}
}
}
}
其中full_name是全文本分词、status是关键字
通过多字段,可以让同一个字段同时拥有全文本和关键字两个版本
字符串数据类型字段可授受的参数:
参数 说明
analyzer 分词器,用于可分词字段。默认为默认的索引分词器或者标准分词器
boost 字段级索引加权。授受浮点型数字,默认为1.0
doc_values 定义字段是否应该以列跨度的方式存储在磁盘,以便用于排序、聚合或者脚本。接受true或false。对于不可分词字段默认为true,可分词字段不支持该参数
fielddate 决定字段是否可以使用内存字段进行排序、聚合或在脚本中使用。接受disabled或paged_bytes(默认)。没有分析过的字段会优先使用文档值
ignore_above 不索引或执行任何长于这个值的字符串。默认为0(禁用)
include_in_all 决定字段是否包含在_all字段中。接受true或false。如果索引被设置为no或父对象字段设置为include_in_all为false。默认为false;其它情况下默认为true
index 决定字段是否可以被用户搜索,接受参数analyzed(默认,视为全文本),not_analyzed(关键字)以及no
index_options 定义存储在索引中,用于搜索和突出用途的信息
norms 计算查询得分的时候是否应该考虑字段长度。默认依赖于索引设置:analyzed字段默认为{“enabled”:true,“loading”:“lazy”},
not_analyzed默认为{“enabled”:false}
null_value 接受一个字符串值替换所有null值,默认为null,意味着字段做为缺失字段。如果字段是可分词的,null_value也会被分词
position_
increment_gap 定义字符串数组中应该插入的虚拟索引词的数量。默认为100,以一个较合理的值来阻止短语查询在跨字段匹配索引词时候的溢出
store 决定字段值是否应该被存储以及从_source字段分别获取。接受true或false(默认)
search_analyzer 用在可分词字段上的分词器
search_quote_
analyzer 指定搜索短语时使用的分词器
similarity 指定使用相似度评分算法,默认为TF/IDF
term_vector 定义一个可分词字段是否应该存储索引词向量,默认no
数字型
参数 说明
long 有符号64位整数,-263至263-1
integer 有符号32位整数,-231至231-1
short 有符号16位整数,-32768至32767
byte 有符号8位整数,-128至127
double 64位双精度浮点数
float 32位单精度浮点数
PUT secisland
{
“mappings”: {
“secilog”: {
“properties”: {
“number_of_bytes”: {
“type”: “integer”
},
“time_in_seconds”: {
“type”: “float”
}
}
}
}
}
数字型字段参数
参数 说明
coerce 试着将字符串转换为整数型数字
boost 字段级索引加权,接受浮点型数字参数,默认为1.0
doc_values 定义字段是否以列跨度的方式存储在磁盘上,以便于排序、聚合或脚本。接受true或false
ignore_malformed 为true时,畸形的数字会被忽略;如果false(默认),畸形数字会抛出异常并丢弃整个文档
include_in_all 决定字段是否应该包含在_all字段中。接受true或false。如果索引被设置为no或父对象字段设置为include_in_all为false。默认为false;其它情况下默认为true
index 决定字段是否可以被搜索。接受参数not_analyzed(默认)和no
null_value 接受与字段同类型的数字型值来代替null值。默认是null,意味着字段作为缺失字段
precision_step 控制索引的额外索引词的数量来使范围查询更快速。默认值取决于数字类型
store 决定字段值是否应该存储以及从_source字段分别获取。接受true或false
日期型
JSON没有日期型数据类型,所以es中日期可以是:
包含格式化日期的字符串:“2018-01-01”,“2018/01/01 12:00:00”
代表时间毫秒数的长整型数字
代表时间秒数的整数
通常,日期被转换为UTC(如果时区被指定)存储为代表时间毫秒数的长整数
可以自定义时间格式,如果没有指定格式,则使用默认值:“strict_date_optional_time||epoch_millis”
{“mappings”:{“secilog”:{“properties”:{“date”:{“type”:“date”}}}}}这将支持"2018-01-01",“2018-01-01T12:00:00Z”,1420070400001这些形式
多日期格式
使用||分隔,可以指定多个日期格式。每个格式会被依次尝试,直到匹配的格式
{“type”:“date”,“format”:“yyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis”}
字段参数
布尔型
接受true或者false,也可以接受代表真或者假的字符串和数字
假值:false,“false”,“off”,“no”,“0”,""空字符串,0,0.0
真值:其他任何非假的值
{“type”:“boolean”}
索引词聚合之类的聚合使用1和0作为key,使用字符串"true"和"false"作为key_as_string。使用脚本时,布尔字段返回1和0。
二进制
接受Base64编码字符串的二进制值。字段不以默认方式存储而且不能搜索
{“type”:“binary”}
Base64编码二进制值不能嵌入换行符\n
字符参数:
doc_values 定义字段是否应该以列跨度的方式存储在磁盘上,以便于排序、聚合或者脚本。接受true(默认)或false
store 决定字段值是否应该存储以及从_source字段分别获取。接受true或false(默认)
复杂数据类型
数组数据类型
每个字段默认可以包含零个或更多的值,但数组中所有的值都必须是相同的数据类型,如
字符串数组:[“one”,“two”]
整数数组:[1,2]
由数组组成的数组:[1,[2,3]],等同于[1,2,3]
对象数组:[{“name”:“Mary”,“age”:12},{“name”:“John”,“age”:10}]
注意,无法对数组中的每一个对象进行单独的查询
当动态添加字段时,数组中第一个元素的值决定了字段类型,后面的所有值必须是相同的数据类型或者可以强制转换为相同的数据类型
es不支持混合数据类型的数组,如[10,“some string”]
数组可能包含null值,会被null_value配置替换或者忽略掉。一个空数组[]被当作缺失字段(没有值的字段)
对象数据类型
JSON是天然分层的,文档可以包含内部对象,内部对象还可以包含内部对象
{“region”:“US”,“manager”:{“age”:30,“name”:{“first”:“John”,“last”:“Smith”}}}
本质上,文档被简单地索引为键值对列表:
{
“region”: “us”,
“manager.age”: 30,
“manager.name.first”: “John”,
“manager.name.last”: “Smith”
}
映射为:
{
“mappings”: {
“secilog”: {
“properties”: {
“region”: {
“type”: “string”,
“index”: “not_analyzed”
},
“manager”: {
“properties”: {
“age”: {
“type”: “integer”
},
“name”: {
“properties”: {
“first”: {
“type”: “string”
},
“last”: {
“type”: “string”
}
}
}
}
}
}
}
}
}
映射类型是一种对象类型,拥有参数字段。manager字段是一个内部对象字段,manager.name字段是manager字段中的内部对象字段。可以明确的设置type字段为object(默认值)。对象数据类型参数
dynamic 定义新的参数是否应该动态加入到已经存在的对象中。接受true(默认),false和strict
enabled 赋值给对象字段的JSON值应该被解析和索引(true,默认),还是完全忽略false
include_in_all 为对象内所有属性设置include_in_all值。对象本身不添加到_all字段
properties 对象内的字段可以是任意数据类型,包括对象数据类型。新的属性可以添加到已存在的对象中
嵌套数据类型
对象数据类型的一个专门版本,用来使一组对象被单独索引和查询
对象数组摊平,可能会引起关联性的丢失,要解决这个问题,可以使用嵌套数据类型
要对一组对象进行索引且保留数组中每个对象的独立性,应该使用嵌套数据类型而不是对象数据类型
嵌套数据类型将数组中每个对象作为分离出来的隐藏文档进行索引,意味着每个嵌套对象可以独立于其他对象被查询
PUTsecisland {“mappings”:{“secilog”:{“properties”:{“user”:{“type”:“nested”}}}}}
插入数据
PUTsecisland/secilog/1 {“group”:“fans”,“user”:[{“first”:“John”,“last”:“Smith”},{“first”:“Alice”,“last”:“White”}]}
这时可以根据对象进行搜索,但对象条件要全匹配才能搜索到
POSTsecisland/_search {“query”:{“nested”:{“path”:“user”,“query”:{“bool”:{“must”:[{“match”:{“user.first”:“Alice”}},{“match”:{“user.last”:“White”}}]}}}}}嵌套数据类型字段参数
dynamic 定义新的参数是否应该动态加入到已经存在的对象中,接受true(默认),false,strict
include_in_all 设置所有嵌套对象属性的include_in_all值。嵌套文档没有它自身的_all字段,取而代之的是,值被添加到"根"文档的_all字段中
properties 嵌套对象的字段可以是任何数据类型,包括嵌套对象类型。新的属性可以被添加到已经存在的嵌套对象中。
地理数据类型
地理点数据类型
经纬度对
查找一定范围内的地理点,范围可以是相对于一个中心点的固定距离或者多边形或者地理散列单元
通过地理位置或者相对于中心点的距离聚合文档
整合距离到文档的相关性评分
通过距离对文档进行排序
PUTsecisland {“mappings”:{“seciclog”:{“properties”:{“location”:{“type”:“geo_point”}}}}}
存储地理位置有4种方式,顺序为经度、纬度
POST secisland/secilog/1
{“text”:“Geo_point as an object”,“location”:{“lat”:41.12,“lon”:-71.34}}
POST secisland/secilog/3 {“text”:“Geo_point as string”,“location”:“41.12,-71.22”}
POST secisland/secilog/4 {“text”:“Geo_point as geohash”,“location”:“drm3btev3e86”}
POST secisland/secilog/5 {“text”:“Geo_point as array”,“location”:[-71.45,41.34]}
地理形状数据类型
索引和搜索任意地理形状,在地理点的基础上包含地理形状
地理形状映射将geo_json几何对象映射成地理形状
前缀树:形状转换成一系列表示为方格(栅格)的散列用于实现一个前缀树。可以为多层网络,对应为不同的精度,提高地图缩放级别
空间策略:前缀树的实现基于空间策略来分解提供的形状为近似方格
准确性:地理形状不提供100%的准确性,且取决于匹配值。可能对确实的查询返回一些误判或者漏判,为缓和这种情况,需要为tree_levels参数选择一个合适的值来适应相应的预期
{“properties”:{“location”:{“type”:“geo_shape”,“tree”:“quadtree”,“precision”:“1m”}}}
上面这个映射将location映射到地理形状类型,使用quad前缀树且精度为1m。es转换这个精度到tree_levels 26
性能考虑:索引大小和合理水平的精确值的折中是50m
输入结构:
示例:
Point是单独的坐标点,如建筑的位置或者智能手机地理定位接口提供的确切位置
{“location”:{“type”:“point”,“coordinates”:[-77.03653,38,897676]}}
Linestring通过两个或更多的一组位置定义。只指定两个点时,表示一条直线;指定更多的点,可以创建任意的线
{“location”:{“type”:“linestring”,“coordinates”:[[-77.03653,38.897676],[-77.009051,38.889939]]}}
Polygon通过一列地理点列表进行定义。每个列表中的第一个点和最后一个点必须相同,多边形必须是封闭的
{“location”:{“type”:“polygon”,“coordinates”:[[[100.0,0.0],[101.0,0.0],[101.0,1.0],[100.0,1.0],[100.0,0.0]]]}}
#第一个数组表示外环边界,其他数组表示内部形状(孔)
#外环:逆时针方向 内环/孔:顺时针方向
#orientation参数可以声明顶点的顺序,可以在映射中定义,也可以在文档中被重写:“orientation”:“clockwise”
MultiPoint是GeoJSON点的列表
MultiLineString是GeoJSON线的列表
MultiPolygon是GeoJSON多边形的列表
GeometryCollection是GeoJSON地理几何对象的集合
Envelope包含矩形左上角和右下角的坐标值
Circle包含圆心和半径
{“location”:{“type”:“circle”,“coordinates”:[-45.0,45.0],“radius”:“100m”}}
地理形状值只能通过_source字段取回
专门数据类型
IPv4数据类型
本质上是一个长整形字段
PUT secisland {“mappings”:{“secilog”:{“properties”:{“ip_addr”:{“type”:“ip”}}}}}
POST secisland/secilog/1 {“ip_addr”:“192.168.1.1”}
单词计数数据类型
本质上是一个整数型字段,授受并分析字符串值,然后索引字符串中单词的个数
PUTsecisland {“mappings”:{“secilog”:{“properties”:{“name”:{“type”:“string”,“fields”:{“length”:{“type”:“token_count”,“analyzer”:“standard”}}}}}}}
插入数据:POST secisland/secilog/1 {“name”:“John Smith”}
单词计数类型计算位置增量而不是统计单词,所以即使过滤掉一部分单词,它们也包含在计数中
3.3元字段
元字段是为保证系统正常运转的内置字段,以下划线开头。当映射类型被创建时,可以自定义一些元字段,如标识元字段/文档来源元字段/索引元字段/路由元字段等
介绍些常用字段
_all字段
一个特殊的包含全部内容的字段,在一个大字符串中关联所有其他字段的值,使用空格作为分割符,可以被分析和索引,但是不被存储
使用_all可以对文档的值进行搜索而不必知道包含所需值的字段名
PUTsecisland/secilog/1 {“first_name”:“John”,“last_name”:“Smith”,“date_of_birth”:“1970-10-24”}
利用_all搜索
POST secisland/_search {“query”:{“match”:{“_all”:“john smith 1970”}}}
_all字段包含索引词[“john”,“smith”,“1970”,“10”,“24”]。date_of_birth会索引一个索引词1970-10-24 00:00:00UTC,但是在_all字段中日期值只作为三个字符串被索引"1970",“10”,“24”
_all字段是一个字符串类型字段,接受与字符串字段相同的参数,包括analyzer,index_options,store
_all字段关联字段值时,丢弃了短字段与长字段的区别,所以当相关性是重要搜索条件时,应该指明查询字段,而不是使用_all
_all字段的使用会需要额外的处理器周期和磁盘空间,所以如果不需要的话,可以完全禁用或者在每个字段的基础上自定义
_field_names字段
_field_names字段索引文档中所有包含非空值的字段名称。用于在存在查询和缺失查询中,查找指定字段拥有非空值的文档是否存在
_field_names字段的值可以用于查询、聚合以及脚本
PUT secisland/secislog/2 {“title”:“this is a document”}
PUT secisland/secislog/2 {“title”:“this is another document”,“body”:“this document has a body”}
POST secisland/secislog/_search
{“query”:{“terms”:{“_field_names”:[“title”]}},“aggs”:{“Field names”:{“terms”:{“field”:“_field_names”,“size”:10}}},“script_fields”:{“Field names”:{“script”:“doc[‘_field_names’]”}}}
_id字段
_id字段没有索引,其值可以从_uid字段自动生成
_id字段的值可以在查询以及脚本中访问,但在聚合或者排序时,要使用_uid字段而不能用_id字段
#在查询和脚本中使用_id字段
POSTsecisland/secislog/_search {“query”:{“terms”:{“_id”:[“1”,“2”]}},“script_fields”:{“UID”:{“script”:“doc[‘_id’]”}}}
_index字段
在多个索引中执行查询时,有里需要添加查询子句来关联特定的索引文档。_index字段可以匹配包含某个文档的索引
在term或terms查询、聚合、脚本以及排序时,可以访问_index字段的值
_index是一个虚拟字段,不作为真实字段添加到lucene中,这意味着可以在term terms或任何重写term的查询,如match、query_string、simple_query_string中使用,但是不支持prefix、wildcard、regexp、fuzzy查询
POST index_1,index_2/_search
{“query”:{“terms”:{“_index”:[“index_1”,“index_2”]}},“aggs”:{“indices”:{“terms”:{“field”:“_index”,“size”:10}}},“sort”:[{“_index”:{“order”:“asc”}}],“script_fields”:{“index_name”:{“script”:“doc[‘_index’]”}}}
_meta字段
每个映射类型都可以拥有自定义元数据,这些元数据对es来说毫无用处,但可以用来存储应用程序的特定元数据
PUTsecisland {“mappings”:{“user”:{“_meta”:{“class”:“MyApp::User”,“version”:{“min”:“1.0”,“max”:“1.3”}}}}}
_parent字段
在同一个索引中通过创建映射类型可以在文档间建立父子关系
PUTsecisland {“mappings”:{“my_parent”:{},“my_child”:{“_parent”:{“type”:“my_parent”}}}}
插入父文档:PUT secisland/my_parent/1 {“text”:“this is a parent document”}
插入子文档并指定父文档:
PUT secisland/my_child/2?parent=1 {“text”:“this is a child document”}
PUT secisland/my_child/3?parent=1 {“text”:“this is another child document”}
1、父子限制
父类型和子类型必须是不同的,父子关系不能建立在相同类型的文档之间
_parent的type设置只能指向一个当前不存在的类型,这意味着一个类型被创建后就无法成为父类型
父子文档必须索引在相同分片上,parent编号用于作为子文档的路由值,确保子文档被索引到父文档所在的分片中
获取、删除或者更新子文档时,需要提供相同的parent值
2、整体序数
使用整体序数可以加快建立父子关系,分片发生任何改变后,整体序数都需要进行重建
整体序数默认为懒创建,可以通过参数将由查询触发改为刷新触发
PUTsecisland {“mappings”:{“my_parent”:{},“my_child”:{“_parent”:{“type”:“my_parent”,“fielddata”:{“loading”:“eager_global_ordinals”}}}}}
_routing字段
文档在索引中通过下面公式路由到特定分片:
shard_num = hash(_routing) % num_primary_shards
_routing字段默认值使用文档_id字段,若存在父文档,则使用文档的_parent编号
可以通过为每个文档指定自定义路由值来实现自定义路由
PUT secisland/secilog/1?routing=user1 {“title”:“this is a document”}
使用user1作为路由,在获取、删除和更新文档时需要提供相同的路由值
_routing字段可以在查询、聚合、脚本以及排序时访问
POSTsecisland/_search {“query”:{“terms”:{“_routing”:[“user1”]}},“aggs”:{“Routing values”:{“terms”:{“field”:“_routing”,“size”:10}}},“sort”:[{“_routing”:{“order”:“desc”}}},“script_fields”:{“Routing value”:{“script”:“doc[‘_routing’]”}}}
1、利用自定义路由进行搜索
自定义路由可以降低搜索压力,搜索请求可以仅仅发送到匹配指定路由值的分片而不是广播到所有分片
POSTsecisland/_search?routing=user1,user2 {“query”:{“match”:{“title”:“document”}}}
搜索请求仅在关联路由值为user1和user2的分片上执行
2、使路由值成为必选项
使用自定义路由索引、获取、删除或者更新文档时,提供路由值非常重要
忘记路由值会导致文档被一个以上分片索引,作为保障,_routing字段可以被设置,使自定义路由值成为所有CRUD操作的必选项
PUT secisland {“mappings”:{“secilog”:{“_routing”:{“required”:true}}}}
3、自定义路由下的唯一编码
当索引指定自定义路由的文档时,不能保障所有分片_id的唯一性,只能依靠用户来确保编码的唯一性
_source字段
_source字段包含索引时原始的JSON文档内容,字段本身不建立索引,无法搜索,但会被存储,所以执行获取请求时,可以返回_source字段
_source字段会对索引产生存储开销,因此可以禁用_source字段
PUT secisland {“mappings”:{“secilog”:{“_source”:{“enabled”:false}}}}
可以通过提高压缩等级来实现节约存储空间,可以用包含/排除字段的特性在保存之前减少数据量
如果_source字段被禁用,会造成大量功能不可用:
#更新接口
#高亮显示功能
#重建索引功能,包含修改映射或者分析,升级索引到新的版本
#通过查看索引时的原始文档对查询或聚合进行调试的功能
#自动修复索引的功能
#从_source字段移除内容相当于精简版的禁用功能,尤其是无法重建文档索引
includes/excludes参数,可以使用通配符
PUTlogs {“mappings”:{“event”:{“_source”:{“includes”:[“.count","meta.”],“excludes”:[“meta.description”,“meta.other.*”]}}}}
移除的字段不会存储在_source中,但仍然可以搜索这些字段
_type字段
每个索引的文档都包含_type和_id字段,_type字段的目的是通过类型名加快搜索进度
_type字段的值可以在查询、聚合、脚本以及排序中访问
PUT secisland/type_1/1 {“text”:“document with type 1”}
PUT secisland/type_2/2 {“text”:“document with type 2”}
POST secisland/_search
{“query”:{“terms”:{“_type”:[“type_1”,“type_2”]}},“aggs”:{“types”:{“terms”:{“field”:“_type”,“size”:10}}},“sort”:[{“_type”:{“order”:“desc”}}],“script_fields”:{“type”:{“script”:“doc[‘_type’]”}}}
_uid字段
每个索引的文档都包含_type和_id字段,这两个值结合为{type}#{id}并且作为_uid字段被索引
_uid字段在查询、聚合、脚本以及排序时访问
PUT secisland/secilog/1 {“text”:“document with id 1”}
PUT secisland/secilog/2 {“text”:“document with id 2”}
POSTsecisland/_search {“query”:{“terms”:{“_uid”:[“secilog#1”,“secilog#2”]}},“aggs”:{“UIDs”:{“terms”:{“field”:“_uid”,“size”:10}}},“sort”:[{“_uid”:{“order”:“desc”}}],“script_fields”:{“UID”:{“script”:“doc[‘_uid’]”}}}
3.4映射参数
映射参数对字段映射的特殊需求进行设置,包括字段分词、权重、是否被索引、日期格式等
analyzer参数
分词,分析器
分析的过程不仅发生在索引阶段,也发生在查询阶段:查询字符串需要通过相同、相似分析器进行分析。查询中的索引词和索引中的索引词具有相同格式
es查找分析器的顺序:
1、字段映射中定义的分析器
2、索引设置中名为default的分析器
3、标准分析器
4、在查询时,有更多的层次
5、在全文查询中定义的分析器
6、在字段映射中定义的搜索分析器
7、在字段映射中定义的分析器
8、在索引设置中名为default_search的分析器
9、在索引设置中名为default的分析器
10、标准分析器
为特定字段指定分词器最简单的方式是在字段映射中定义
PUTsecisland {“mappings”:{“secilog”:{“properties”:{“text”:{“type”:“string”,“fields”:{“english”:{“type”:“string”,“analyzer”:“english”}}}}}}}
search_quote_analyzer参数可以对短语指定一个分析器,当处理禁用短语连接词的查询特别有用
为禁用短语连接词,字段需要利用三个分析器设置:
1、analyzer设置,用于索引包括连接词在内的所有索引词
2、search_analyzer设置,用于移除连接词的非短语查询
3、search_quote_analyzer设置,用于包括连接词在内的短语查询
插入数据:
PUT secisland/secilog/1 {“title”:“The Quick Brown Fox”}
PUT secisland/secilog/2 {“title”:“A Quick Brown Fox”}
进行短语查询:
POST secisland/secilog/_search {“query”:{“query_string”:{“query”:““the quick brown fox””}}}
当查询被包含在引号中时,表示为短语查询,search_quote_analyzer生效并确保查询中包含连接词
如果没有search_quote_analyzer,短语查询不能被精确匹配,两个文档都会被匹配
boost参数
在索引时,通过boost参数可以对一个字段进行加权,相关性得分更多
PUTsecisland {“mappings”:{“secilog”:{“properties”:{“title”:{“type”:“string”,“boost”:2},“content”:{“type”:“string”}}}}}
此时title字段会有两倍加权,而content字段为默认值1
title字段通常比content字段短,默认的相关性计算需要考虑字段长度,因此短的字段会有一个更高的加权
索引时最好不要加权,因为除非重索引所有文档,索引加权值不会发生改变;每个查询都支持查询加权,会产生相同的效果,不同的地方在于不需要重索引就可以调整加权;
索引加权做为norm的一部分,只有一个字节,这降低了字段长度归一化因子的分辨率,会导致低质量的相关性计算
索引加权的唯一优势在于作用于_all字段,这意味着查询_all字段时,titlte字段的词会有更高的分数,但这是以计算成本为代价的,查询_all字段会变得更加缓慢
coerce参数
数据不都是干净的,强制尝试清理脏值来匹配字段的数据类型,如:
字符串会被强制转换为数字
浮点型数据会被截取为整形数据
经纬地理点数据会归一化到标准-180:180/-90:90坐标系
copy_to参数 复制域
利用copy_to可以创建自定义的_all字段。即多个字段的值可以被复制到一组字段,然后可以作为单个字段进行查询
PUT secisland
{
“mappings”: {
“secilog”: {
“properties”: {
“first_name”: {
“type”: “string”,
“copy_to”: “full_name”
},
“last_name”: {
“type”: “string”,
“copy_to”: “full_name”
},
“full_name”: {
“type”: “string”
}
}
}
}
}
插入数据:
PUT secisland/secilog/1
{“first_name”:“John”,“last_name”:“Smith”}
查询:
POST secisland/secilog/_search
{“query”:{“match”:{“full_name”:{“query”:“John Smith”,“operator”:“and”}}}}
first_name和last_name字段的值会被复制到full_name字段中,first_name和last_name可以单独查询,full_name可以同时查询两个字段的内容
要点:
字段的值是复制过来的,而不是分析的结果
原始的_source字段不会展示复制的值
“copy_to”:[“field_1”,“field_2”]可以将相同值复制到多个字段
doc_values参数
大多数字段默认被索引,拿其可以被搜索到。文档值doc_values是磁盘上的数据结构,几乎支持所有字段类型,所有字段默认都包含在文档值中
如果确定某个字段不需要排序、聚合或脚本中访问,可以禁用文档值以节省存储空间。没有文档值的字段依然可查询
PUT secisland
{
“mappings”: {
“secilog”: {
“properties”: {
“status_code”: {
“type”: “string”,
“index”: “not_analyzed”
},
“session_id”: {
“type”: “string”,
“index”: “not_analyzed”,
“doc_values”: false
}
}
}
}
}
同一个索引中,同名字段可以有不同的doc_values,可以通过PUT映射接口对其进行操作
dynamic参数
动态根据数据生成mapping的
默认,字段可以被动态添加到一个文档中,或者添加到文档内部对象中,仅仅通过索引一个包含新字段的文档
dynamic控制新字段是否可以被动态添加,接受三种设置:
true,新检测到的字段会被添加到映射中(默认)
false,新检测到的字段会被忽略,新字段必须明确添加
strict,如果检测到新字段,抛出异常,丢弃文档
dynamic可以在映射类型级别以及每个内部对象被设置,内部对象从父对象或映射类型中继承设置值
PUT secisland
{
“mappings”: {
“secilog”: {
“dynamic”: false,
“properties”: {
“user”: {
“properties”: {
“name”: {
“type”: “string”
},
“social_networks”: {
“dynamic”: true,
“properties”: {}
}
}
}
}
}
}
}
#动态映射在类型级别被禁用,所有顶级字段不会被自动添加,user.social_networds对象启用了动态映射,可以添加新的内部对象
enabled参数
仅存储字段而不进行索引,enabled可以被用于映射类型和对象字段,JSON仍然可以从_source字段取回,但不能搜索或以其他方式存储
整个映射类型都可以被禁用,在这种情况下,文档被存储在_source字段,可以被取回,但没有任何内容以任何方式被索引
{“mappings”:{“session”:{“enabled”:false}}}
fielddata参数
在排序、聚合或脚本中访问字段值可以通过doc_values实现访问,但是分析过的字符串字段不支持doc_values。
分词的字符串在查询时利用字段数据fielddata的数据结构,这个数据结构在字段被用于聚合、排序或脚访问的第一时间创建
字段数据有三个参数,format表示是否启用,loading用的时机和filter过滤加载的数据
加载字段数据是一个昂贵的过程,一但被加载,就会在分片的生命周期内驻留在内存中
字段数据会消耗大量堆内存空间,特别在加载高基数分词字符串字段,可以考虑字段是否不可分词(可以使用doc_values)以更好的适应场景
同一个索引中同名字段必须拥有相司的fielddata.设置
1、fielddata.format
对于分词字符串字段,format参数用来控制字段是否应该被启用,接受disabled和paged_bytes(启用,默认值)
禁用字段数据加载,可以使用下面的设置
PUT secisland {“mappings”:{“secilog”:{“properties”:{“text”:{“type”:“string”,“fielddata”:{“format”:“disabled”}}}}}}
通过设置,test字段不能被用于排序、聚合或脚本
2、fielddata.loading
针对每个字段的设置,控制字段数据加载到内存的时机,接受三个参数:
lazy 仅在需要时加载到内存中(默认)
eager 在新的搜索分片对搜索可见之前,就加载到内存中。对于大容量分片,提前加载,可以减少请求延迟
eager_global_ordinals 仅加载必须的部分到内存中。加载后,es创建整体序数数据结构来组成一个所有索引词的列表。默认请况下,整体序数是被动创建的,如果字段有非常高的基数,可以使用主动加载
3、fielddata.filter
字段数据过滤可以用来减少加载到内存中的索引词数量,可以减少内存使用量。索引词可以通过频率或正则表达式以及两者的配合进行过滤
频率可以表示为确切的数字(数值大于1.0时)或百分比(数值小于等于1.0,1.0即为100%)
可以通过min_segment_size参数指定分片应该包含的最少文件量来完全排除小容量分片:
PUT secisland {“mappings”:{“secilog”:{“properties”:{“tag”:{“type”:“string”,“fielddata”:{“frequency”:{“min”:0.001,“max”:0.1,“min_segment_size”:500}}}}}}}
索引词也可以通过正则表达式进行过滤:只有匹配正则表达式的值会被加载,正则表达式应用于字段中的每个索引词,而不是整个字段值
PUT secisland {“mappings”:{“secilog”:{“properties”:{“secilog”:{“type”:“string”,“analyzer”:“whitespace”,“fielddata”:{“filter”:{“regex”:{“pattern”:"^#."}}}}}}}}
format参数
JSON文档中,日期用字符串表示,es利用预先定义的格式来识别和分析,并产生一个长整型数值,代表世界标准时间的毫秒数
除了内置格式,可以通俗的yyyy/MM/dd语法来指定自定义格式
PUT secisland
{“mappings”:{“secilog”:{“properties”:{“date”:{“type”:“date”,“format”:“yyyy-MM-dd”}}}}}
支持日期值的接口也支持日期匹配表达式,如now-1m/d表示当前时间减去1个月,并四舍五入到最近的一天
同一个索引中同名字段必须有相同格式设置,已有字段可以通过PUT映射接口更新
支持的日期格式:
geohash参数
地理散列是把地球划分为网格的经纬度编码。地理散列越长,单元格越小,精确度超高,地理散列的长度通过geohash_precision控制
如果启用geohash_prefix,geohash选项会被自动启动
PUT secisland {“mappings”:{“secilog”:{“properties”:{“location”:{“type”:“geo_point”,“geohash”:true}}}}}
PUT secisland/secilog/1 {“location”:{“lat”:41.12,“lon”:-71.34}}
每个地理点都会索引一个location.geohash字段,地理散列可以从doc_values中取回
geohash_precision参数
当启用地理散列是,地理精度设置可以控制地理散列的长度,当地理散列前缀启用时,地理精度设置可以控制散列的最大长度
接受参数:介于1到12(默认)之前的数字,代表地理散列长度;一段距离,如1km,最小的地理散列长度请求分辩率
PUT secisland {“mappings”:{“secilog”:{“properties”:{“location”:{“type”:“geo_point”,“geohash_prefix”:true,“geohash_precision”:6}}}}}
PUT secisland/secilog/1 {“location”:{“lat”:41.12,“lon”:-71.34}}
geohash_precision值为6时地理散列单元格面积近似为1.26km*0.6km
geohash_prefix参数
当启用地理散列选项,以一定精度将地理散列作为经纬度索引时,geohash_prefix选项也会索引到所有地理散列单元格中
如,一个drm3btev3e86地理散列会索引下列所有的索引词【d,dr,drm,drm3,drm3b…drm3btev3e86】,在geohash_cell查询中可以使用地理散列前缀查找特定的点,或者它的相邻点
PUT secisland {“mappings”:{“secilog”:{“properties”:{“location”:{“type”:“geo_point”,“geohash_prefix”:true,“geohash_precision”:6}}}}}
PUT secisland/secilog/1 {“location”:{“lat”:41.12,“lon”:-71.34}}
POST secisland/_search?fielddata_fields=location.geohash {“query”:{“geohash_cell”:{“location”:{“lat”:41.02,“lon”:-71.48},“precision”:4,“neighbors”:true}}}
ignore_above参数
超过ignore_above参数设置长度的字符串不会被分词或者索引。主要用于不分词的字符串字段,这些字符串常用于过滤、聚合、排序
这些都是结构化的字段,让这些字段索引非常长的索引词通常是不明智的
PUT secisland {“mappings”:{“secilog”:{“properties”:{“message”:{“type”:“string”,“index”:“not_analyzed”,“ignore_above”:20}}}}}
#message字段会忽略任何长度超过20个字符的字符串
#当message字段长度超过20个字符后,整个文档会被索引,但不会索引message字段的值
ignore_malformed参数
默认在试着索引错误的数据类型时会抛出异常并拒绝整个文档,如果ignore_malformed参数设为true,那么异常会被忽略,错误字段不会被索引(会存储值),但文档中的其他字段会正常处理
PUT secisland {“mappings”:{“secilog”:{“properties”:{“number_one”:{“type”:“integer”},“number_two”:{“type”:“integer”,“ignore_malformed”:true}}}}}
PUT secisland/secilog/1 {“text”:“some text value”,“number_two”:“foo”}
#不会抛出异常,number_two会存储foo
index.mapping.ignore_malformed设置可以用在索引级别上,在所有映射类型中忽略错误内容
PUT secisland {“settings”:{“index.mapping.ignore_malformed”:true},“mappings”:{“secilog”:{“properties”:{“number_one”:{“type”:“byte”},“number_tow”:{“type”:“integer”,“ignore_malformed”:false}}}}}
include_in_all参数
include_in_all参数对每个字段进行控制是否被包含在_all字段中。默认为true,除非索引被设为no
include_in_all还可以设置在类型级别以及对象或嵌入字段,子字段会继承该设置
PUT secisland {“mappings”:{“secilog”:{“include_in_all”:false,“properties”:{“title”:{“type”:“string”},“author”:{“include_in_all”:true,“properties”:{“first_name”:{“type”:“string”},“last_name”:{“type”:“string”}}},“editor”:{“properties”:{“first_name”:{“type”:“string”},“last_name”:{“type”:“string”,“include_in_all”:true}}}}}}}
index参数
控制字段值如何进行索引,以及如何搜索,接受三种值:
no,不要在索引中加入这个字段的值。字段不会被查询到
not_analyzed,字段值原封不动地添加到索引中,作为单一索引词。除了字符串字段之外的所有字段默认支持这个选项
analyzed,该选项仅用在字符串字段上,作为默认选项。字符串首先被分词为一组索引词,然后被索引。搜索时,查询字符串会通过相同分词器生成相同格式索引词,以实现全文搜索
PUT secisland {“mappings”:{“secilog”:{“properties”:{“status_code”:{“type”:“string”,“index”:“not_analyzed”}}}}}
index_options参数
index_options控制将什么信息添加到反向索引,用于搜索和强调的目的,接受参数如下:
docs,只有被索引的文档数量。可解决"字段是否包含这个索引词"的问题
freqs,被索引的文档数量和索引词频率。索引词频率使重复索引词得分高于单个索引词
positions,文档数量,索引词频率以及索引词位置。位置可以被用于邻近或者短语查询
offsets,文档数量,索引词频率、位置以及开始和结束字符偏移量(映射索引词到原始字符串)
分词字符串字段用position为默认值,其他字段用docs为默认值
PUT secisland {“mappings”:{“secilog”:{“properties”:{“text”:{“type”:“string”,“index_options”:“offsets”}}}}}
lat_lon参数
地理查询通过添加每个地理点字段的值到一个公式中,执行这个公式来决定地理点是否落入请求的区域中
设置lat_lon为true会使纬度和经度的值作为数字型字段(称.lat和.lon)被索引。这些字段可以用于地理范围查询和地理距离查询代替执行内存运算
PUT secisland {“mappings”:{“secilog”:{“properties”:{“location”:{“type”:“geo_point”,“lat_lon”:true}}}}}
#lat_lon为true,会在location.lat和location.lon字段索引地理点
PUT secisland/secilog/1 {“location”:{“lat”:41.12,“lon”:-71.34}}
POST secisland/_search {“query”:{“geo_distance”:{“location”:{“lat”:41,“lon”:-71},“distance”:“50km”,“optimize_bbox”:“indexed”}}}
#indexed参数会让地理距离查询利用反向索引值而不是内存运算
是执行内存还是索引操作更好,取决于数据集和执行的查询类型
lat_lon选项仅对单值地理点字段有意义,不会对地理点数组产生效果
fields参数
fields多字段,基于不同的目的用不同的方法索引相内的字段,如一个做为分词用于全文搜索,一个作为不分词用于排序和聚合
PUT secisland {“mappings”:{“secilog”:{“properties”:{“city”:{“type”:“string”,“fields”:{“raw”:{“type”:“string”,“index”:“not_analyzed”}}}}}}}
#city字段是分词字段,可进行全文搜索;city.raw字段不分词,可用来排序或聚合使用多重分词器
多字段的另一种应用是对相同的字段进行不同方式的分词以达到更好的相关性。
如可以利用标准分词器将文本划分为单词,然后利用英文分词器把单词划分为词根的形式
PUT secisland {“mappings”:{“secilog”:{“properties”:{“text”:{“type”:“string”,“fields”:{“english”:{“type”:“string”,“analyzer”:“english”}}}}}}}
#text字段使用标准分词器,text.english字段使用英文分词器
norms参数
norms存储各种标准化系数(一个数字),表示相关字段的长度和索引时相关性加权设置
用于在查询时计算文档对于查询条件的相关性得分,虽然对计算相关性得分非常有用,但norms也需要大量内存
如果不需要在一个特殊的字段上计算相关性得分,应该在字段上禁用norms,此时,字段仅用于过滤或聚合
norms可以通过PUT映射接口取消(不能被重新启用)
PUT secisland/_mapping/secilog {“properties”:{“title”:{“type”:“string”,“norms”:{“enabled”:false}}}}
注:标准值不会立即移除,但索引新文件、旧分片融入新分片时,标准值会被移除,移除已有标准值字段计算出的得分可能会返回不同的结果
标准值延迟加载
当新分片上线,标准值可以被优先eager加载到内存,或当字段被查询时,标准值被延迟加载lazy默认
PUT secisland/_mapping/secilog {“properties”:{“title”:{“type”:“string”,“norms”:{“loading”:“eager”}}}}
null_value参数
空值是不能被索引或搜索的。当一个字段设置为null或者是一个空数组或者null值的数组,这个字段会当作没有值的字段
null_value可以用指定的值替换掉确切的空值,以便可以被索引和搜索
PUT secisland {“mappings”:{“secilog”:{“properties”:{“status_code”:{“type”:“string”,“index”:“not_analyzed”,“null_value”:“NULL”}}}}}
PUT secisland/secilog/1 {“status_code”:null}
PUT secisland/secilog/2 {“status_code”:[]}
注:null_value需要设置和字段相同的数据类型
position_increment_gap参数
为支持短语查询,需要保存可分词字符串字段中分词的位置。当字符串字段索引多个值,一个“虚拟”缺口被添加到各个值之间防止短语查询跨值匹配,缺口大小通过position_increment_gap配置,默认值100
PUT secisland {“mappings”:{“secilog”:{“properties”:{“names”:{“type”:“string”,“position_increment_gap”:0}}}}}
#下一个元素数组的第一个索引词与上一个元素数组的最后一个索引词之间0个索引词间隔,短语查询匹配将表现为怪异,非预期
precision_stip参数
数字型数据类型索引额外的索引词表示每个数字的范围,使范围查询更加便捷
“range”:{“number”:{“gte”:0,“lte”:321}}
这从本质上作为索引词查询,结构为:
“terms”:{“number”:[“0-255”,“256-319”,“320”,“321”]}
precision_step默认值取决于数字型字段的类型
properties参数
类型映射,对象字段和嵌套类型字段包含子字段,称为属性。这些属性可以是任何数据类型,包含对象和嵌套类型,属性在以下情况添加:
创建索引时明确定义
利用映射接口添加或修改映射类型时明确定义
索引包含新字段的文档可以动态添加
PUT secisland {“mappings”:{“secilog”:{“properties”:{“manager”:{“properties”:{“age”:{“type”:“integer”},“name”:{“type”:“string”}}},“employees”:{“type”:“nested”,“properties”:{“age”:{“type”:“integer”},“name”:{“type”:“string”}}}}}}}
点符号: 查询、聚合等方法可以使用点符号获取内部字段
POST secisland/_search {“query”:{“match”:{“manager.name”:“Alice White”}},“aggs”:{“Employees”:{“nested”:{“path”:“employees”},“aggs”:{“Emplyee Ages”:{“histogram”:{“field”:“employees.age”,“interval”:5}}}}}}
#必须指定内部字段的完整路径
search_analyzer参数
通常,索引时和搜索时使用的分词器是相同的,但可以通过search_analyzer为搜索时指定不同的分词器
PUT secisland {“settings”:{“analysis”:{“filter”:{“autocomplete_filter”:{“type”:“edge_ngram”,“min_gram”:1,“max_gram”:20}},“analyzer”:{“autocomplete”:{“type”:“custom”,“tokenizer”:“standard”,“filter”:[“lowercase”,“autocomplete_filter”]}}}},“mappings”:{“secilog”:{“properties”:{“text”:{“type”:“string”,“analyzer”:“autocomplete”,“search_analyzer”:“standard”}}}}}
similarity参数
es允许对每个字段配置得分算法或相似算法。similarity参数提供一个简单的方式来选择不同于默认的TF/IDF算法,例如BM25
相似算法多用于字符串字段,特别是可分词的字符串字段,但也可以应用于其他字段类型
自定义相似算法可以通过调整内置相似算法的参数进行配置
不用更多配置就可直接使用的相似算法有:
default,es和lucene默认的TF/IDF算法
BM25,Okapi BM25算法
相似算法可以在字段第一次创建时在字段级别上进行设置
PUT secisland {“mappings”:{“secilog”:{“properties”:{“default_field”:{“type”:“string”},“bm25_field”:{“type”:“string”,“similarity”:“BM25”}}}}}
store参数
默认,字段值被索引来确保可以被搜索,但不会被存储。这意味着可以查询字段,但无法取回原始字段值
通常这没有什么问题,因为字段值是默认_source字段的一部分。如果想取回单个字段或一些字段的值,而不是整个_source字段,可以通过数据源过滤实现
PUT secisland {“mappings”:{“secilog”:{“properties”:{“title”:{“type”:“string”,“store”:true},“date”:{“type”:“date”,“store”:true},“content”:{“type”:“string”}}}}}
#title和date字段会被存储
PUT secisland/secilog/1 {“title”:“this title”,“date”:“2018-08-11”,“content”:“this is content”}
POST secisland/_search {“fields”:[“title”,“date”]} #取回title和date的值
term_vector参数
索引词向量包含分析过程产生的索引词信息,包括:
索引词列表
每个索引词的位置
映射索引词到原始字符串中原始位置中开始和结束字符的偏移量
这些索引词向量会被存储,所以可以作为一个特殊文档取回
term_vector设置接受参数:
no,不存储索引词向量(默认)
yes,只存储字段的索引词
with_positions,索引词和位置将会被存储
with_offsets,索引词和字符偏移量会被存储
with_positions_offsets,索引词,位置以及偏移量都会被存储
PUT secisland {“mappings”:{“secilog”:{“properties”:{“text”:{“type”:“string”,“term_vector”:“with_positions_offsets”}}}}}
3.5动态映射
概念
PUT data/counters/1 {“count”:5}
自动创建索引为data,映射类型为counters,字段名为count,类型为long
_default_映射,用于创建映射类型的基础映射
动态字段映射,控制动态字段检测规则
动态模板,自定义规则来配置动态添加字段的映射
禁用动态类型创建,通过设置index.mapper.dynamic为false来禁用,可以在配置文件或在每个索引中进行设置
PUT _settings {“index.mapper.dynamic”:false} #对所有索引禁用动态类型创建
_default_映射
默认映射,用作每个新映射类型的基础映射,可以通过在索引中增加名为_default_的映射类型来自定义
PUT secisland {“mappings”:{“default”:{“_all”:{“enabled”:false}},“user”:{},“blogpost”:{“_all”:{“enabled”:true}}}}
#default_禁用_all,user继承_default,blogpost重写默认设置,启用_all
_default_映射可以在索引创建后进行修改,新的默认映射只会影响之后创建的映射类型
动态字段映射
默认的,在文档中发现新字段时,会自动添加新字段到类型映射中,这种默认行为可以被禁用,通过设置动态参数为false或strict
若启用动态字段映射,数据类型规则如下表:
可以通过动态模板自定义更多的动态字段映射规则
1、日期检查
默认启用日期检查,如果匹配任何dynamic_date_formats中指定的日期格式,新的日期字段会以相同的格式添加
dynamic_date_formats默认值为[“strict_date_optional_time”,“yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z”]
2、禁用日期检查
设置date_detection为false
PUT secisland {“mappings”:{“secilog”:{“date_detection”:false}}}
3、自定义日期检查格式
PUT secisland {“mappings”:{“secilog”:{“dynamic_date_formats”:[“MM/dd/yyyy”]}}}
4、数字检查
JSON支持浮点型和整型数据类型,一些应用或语言会以字符串传递数字,通常明确定义这些字段映射,但也可以启用数字检查(默认禁用)来自动做类型转换
PUT secisland {“mappings”:{“secilog”:{“numeric_detection”:true}}}
动态模板
动态模板可以定义自定义映射用来动态添加字段,基于以下参数:
通过es进行数据类型检查,利用match_mapping_type参数
字段名,利用match和unmatch或match_pattern参数
字段全路径,利用path_match和path_unmatch参数
原始字段名{name}和数据类型检查{dynamic_type}模板变量可以作为点位符用在映射标准中
动态字段映射仅在字段包含具体值(不为null或空数组)时添加,这意味着如果在dynamic_template中有null_value选项,需要第一个文档中被索引的字段有具体的值后,null_value才会起作用动态模板被指定为命名的对象数组
模板名可以是任何字符串值
匹配条件可以包含所有的:match_mapping_type、match、match_pattern、unmatch、path_match、path_unmatch
mapping包含匹配到的字段需要使用的映射值
模板顺序执行,第一个匹配到的模板起作用,新的模板可以用增加映射接口添加到表的末尾,如果新模板与旧模板名字相同,旧版本会被替换掉
1、match_mapping_type
match_mapping_type根据字段的数据类型进行自定义映射。只有boolean、date、double、long、object、string,也可接受来匹配所有的数据类型
#映射所有整数型字段为integer而不是long,以及所有可分词和不可分词的字符串字段
PUT secisland {“mappings”:{“secilog”:{“dynamic_templates”:[{“integers”:{“match_mapping_type”:“long”,“mapping”:{“type”:“integer”}}},{“strings”:{“match_mapping_type”:“string”,“mapping”:{“type”:“string”,“fields”:{“raw”:{“type”:“string”,“index”:“not_analyzed”,“ignore_above”:256}}}}}]}}}
2、match和unmatch
match使用匹配字符名称的方式;unmatch使用排除match匹配字段的方式
#匹配所有字符串型字段名以long_开头并排除以_text结尾的字段,索引这些字段为长整型字段
PUT secisland {“mappings”:{“secilog”:{“dynamic_templates”:[{“longs_as_strings”:{“match_mapping_type”:“string”,“match”:"long_“,“unmatch”:”_text",“mapping”:{“type”:“long”}}}]}}}
3、match_pattern
match_pattern支持完整的Java正则表达式匹配字段名而不是简单的通配符
“match_pattern”:“regex”
4、path_match和path_unmatch
工作方式与match和unmatch相同,但在字段全路径上进行操作,不仅仅是在最终的名字上
PUT secisland {“mappings”:{“secilog”:{“dynamic_templates”:[{“full_name”:{“path_match”:"name.“,“path_unmatch”:”.middle",“mapping”:{“type”:“string”,“copy_to”:“full_name”}}}]}}}
5、{name}和{dynamic_type}
点位符会被映射中的字段名和字段类型替换
#设置所有字符型字段使用与字段同名的分析器,禁用所有非字符型字段的doc_values参数
PUT secisland {“mappings”:{“secilog”:{“dynamic_templates”:[{“named_analyzers”:{“match_mapping_type”:“string”,“match”:"“,“mapping”:{“type”:“string”,“analyzer”:”{name}“}}},{“no_doc_values”:{“match_mapping_type”:”*",“mapping”:{“type”:“dynamic_type”,“doc_values”:false}}}]}}}
重写默认模板
可以重写所有索引的默认映射,也可以通过在索引模板中指定_default_类型映射重写映射类型
#对所有新索引中的类型禁用_all字段
PUT _template/disable_all_field {“disable_all_field”:{“order”:0,“template”:“*”,“mappings”:{“default”:{“_all”:{“enabled”:false}}}}}
第四章 搜索
DSL
4.1深入搜索
搜索方式的两种方式,
一种是通过URL参数进行搜索,
另一种是通过POST请求参数进行搜索
1.URL参数搜索
请求:GET http://127.0.0.1:9200/secisland/log/_search?参数,多个参数用&分开
GET secisland/_search?q=GET
GET secisland/_search?q=get&explain
GET secisland/_search?q=get&_source=false&fields=method,input
GET secisland/_search?q=get&_source=false&fields=method,input&sort=input:asc
GET secisland/_search?q=get&_source=false&fields=method,input&sort=input:asc&size=2
2.POST请求参数搜索
请求:POST http://127.0.0.1:9200/secisland/doc/_search
参数:JSON格式的查询语法DSL
如:
{
“query”: {
“term”: {
“type”: “www_log”
}
}
}
如果需要分页,可以通过from size组合来进行,from表示从第几行开始,size表示查询多少条文档,from默认为0,size默认为10
size大小不能超过index.max_result_window参数的设置,默认为10000
POST secisland/doc/_search
{
“from”: 0,
“size”: 10,
“query”: {
“term”: {
“type”: “www_log”
}
}
}
排序sort
#优先对type字段进行排序,然后对agent字段进行排序
{
“query”: {
“term”: {
“type”: “www_log”
}
},
“sort”: [
{
“type.raw”: “asc”
},
{
“agent.raw”: “desc”
}
]
}
注意,分析字段不能进行排序,所以需要使用关键字字段type.raw和agent.raw
当一个字段的内容有多个值时,系统支持min/max/sum/avg/median计算排序
#若order有多个值,取平均值排序
{“query”:{…},“sort”:[{“price”:{“order”:“asc”,“mode”:“avg”}}]}
数据列过滤
在查询时不显示原始数据,或者显示部分原始字段
#不显示原始字段
POST secisland/_search
{
“_source”: false,
“query”: {
“term”: {
“type”: “www_log”
}
}
}
#显示部分原始字段
POST secisland/_search
{
“_source”: [
“s*”
],
“query”: {
“term”: {
“type”: “www_log”
}
}
}
#包含或排除某些列
POST secisland/_search
{
“_source”: {
“include”: [
“i*”
],
“exclude”: [
“*e”
]
},
“query”: {
“term”: {
“type”: “www_log”
}
}
}
脚本支持
也就是支持计算
POST secisland/_search
{
“query”: {
“term”: {
“type”: “www_log”
}
},
“script_fields”: {
“test1”: {
“script”: “doc[‘input’].value*2000”
}
}
}
重新评分
在es中,搜索单个单词是比较快的,搜索短语时,效率会比较低,重新评分可以提高查询短语的效率。原理是当在整个索引中搜索短语的资源消耗会比较多,但大多数时候,人们只关心最近发生的一部分文档,可以在最近的一段文档中对短语进行重新评分,在查询时,看起来效率会比较高
滚动查询请求
es中,一次查询只能得到一次独立的结果,在分页中这很不方便。分页时,第n页查询时,实际查询了所有的结果,只是返回时抛弃了前面n-1页的结果
滚动查询类似于数据库中的游标
隐藏内容查询
es中有嵌套结构和父子结构,在父子结构中,可以通过查询子文档的内容返回父文档的内容或者通过父文档查询返回子文档;在嵌套结构中,可以通过嵌套内部对象的查询得到嵌套文档
上面两种情况中,实际匹配内容是隐藏的,如果需要展现实际匹配内容,可以使用隐藏内容查询inner hits
4.1…5搜索相关函数
Preference
搜索分片副本执行偏好设置。默认使用随机副本方法搜索副本的分片。可以通过preference参数设置搜索分片范围
POST /secilog/_search?preference=xyzabc123
通过"version":true可以使每个返回的结果之中有版本号
{
“version”: true,
“query”: {
“term”: {
“message”: “POST”
}
}
}
index_boost索引加权
当搜索多个索引时,可以对每个索引配置不同的索引加权级别。当多个索引存储类似文档时,索引加权特别有用,可以使一个索引命中级别高于另一个索引
{
“indices_boost”: {
“index1”: 1.4,
“index2”: 1.3
}
}
min_score最小分值
可以指定搜索时的最小评分分值
{
“min_score”: 0.5,
“query”: {
“term”: {
“message”: “POST”
}
}
}
explain分值解释
使每个命中的查询解释它的得分是如何计算出来的
{
“explain”: true,
“query”: {
“term”: {
“method”: “post”
}
}
}
_search_shards分片情况查询
GET secisland/_search_shards
_count总数查询
GET secisland/_count
POST secisland/_count
{
“explain”: true,
“query”: {
“term”: {
“method”: “post”
}
}
}
是否存在查询
当设置size为0和terminate_after为1时,可以验证查询是否有结果存在
POST secisland/_search
{
“size”: 0,
“terminate_after”: 1,
“query”: {
“term”: {
“method”: “post”
}
}
}
验证接口
验证一个查询的语法是否正确,这样可以不实际执行,提高效率,防止误操作
POST secisland/_validate/query
{
“query”: {
“term”: {
“method”: “post”
}
}
}
字段状态查询
_field_stats可以对索引字段状态进行查询
GET secisland/_field_stats?fields=times
4.1.6搜索模板
es支持基于模板的查询,可以使用mustache语言作为搜索请求的预处理,它提供模板,通过键值对替换模板中的变量。
模板的使用方式:
直接在请求体中使用脚本
把脚本存储在索引中,通过引用脚本id来使用
把脚本存储在本地磁盘中,默认位置:elasticsearch/config/scripts,通过引用脚本名称进行使用
PUT secilog/log/1
{
“eventCount”: 1,
“eventName”: “linux login event”
}
#第一种方式:请求中
POST secilog/_search
{
“query”: {
“template”: {
“inline”: {
“match”: {
“eventName”: “{{query_string}}”
}
},
“params”: {
“query_string”: “linux”
}
}
}
}
#第二种方式:索引中
#先存储脚本
POST _search/template/templateTest
{
“template”: {
“query”: {
“match”: {
“eventName”: “{{query_string}}”
}
}
}
}
4.2查询DSL
4.2.1查询和过滤的区别
叶查询子句:在特定字段上查找特定的值,如match、term或者range查询
复合查询子句:包含其它叶查询或复合查询子句,以合理的方式结合多条查询,如bool、dis_max 或者改变查询行为,如not、constant_score查询
查询:query,检查内容与条件是否匹配,且计算_score元字段表示匹配度。
过滤:filter,不计算匹配得分,只是简单地决定文档是否匹配。主要用于过滤结构化数据,如时间段 status字段值是否为"published"等
使用过滤通常会被es自动缓存以提高性能
查询子句也可以传递filter参数,如bool查询内的filter/constant_score查询内的filter参数等
举个查询子句的例子。
查询会匹配符合下列所有条件的文档:
title字段包含单词Search。
content字段包含单词Elasticsearch。
status字段包含准确的单词published。
publish_date字段包含从2015年1月1日之后的日期。
#query参数表示内容查询,使用bool和match子句,用于计算每个文档的匹配得分
#filter参数表示内容过滤,使用term和range子句,过滤掉不匹配的文档、不影响文档匹配得分
{“match_all”:{}} 匹配所有文档 文档_score值为1.0
{“match_all”:{“boost”:1.2}} 使用boost修改_score值
4.2.2全文搜索
执行查询前,根据被查询字段的分词方式,在查询字符串上应用被查询字段的映射分词器或搜索分词器
标准查询,授受文本、数字、日期的查询,分析参数并组成查询条件,
如:{“match”:{“message”:“this is a test”}},
其中message为字段名,也可以为_all
有三种类型的match查询:
布尔boolean/
短语phrase/
短语前缀phrase_prefix。
此外还有多段查询、Lucene语法查询、简化查询
1、布尔查询
默认的标准查询类型,分析文本并组成一个布尔查询。operator参数可以设置为or(默认)或者and来控制布尔子句
用于匹配的should子句(可选)的最小数量可以使用minimun_should_match参数来设置
可以设置analyzer来控制在文本上执行分析过程的分析器,默认是字段映射中明确定义或者默认的搜索分词器
lenient参数可以设置为true来忽略数据类型匹配出错造成的异常,默认为false
(1)模糊匹配
fuzziness可以对请求的字段类型进行模糊匹配
prefix_length和max_expansions在这种情况下可以用来控制模糊过程。如果设置模糊选项,查询会使用top_terms_blended_freqs_${max_expansions}作为重写方法。fuzzy_rewrite参数可以控制查询如何进行重写
{
“match”: {
“message”: {
“query”: “this is a test”,
“operator”: “and”
}
}
}
(2)零索引词查询
如果查询使用的分词器移除所有语元,默认行为是不匹配任何文档,可以使用zero_terms_query选项进行修改,接受none(默认)和all(相当于match_all)
{
“match”: {
“message”: {
“query”: “to bo or not to be”,
“operator”: “and”,
“zero_terms_query”: “all”
}
}
}
2、短语查询
短语查询分析文本且创建短语查询
{
“match_phrase”: {
“message”: “this is a test”
}
}
因为短语查询只是标准查询的一个类型,所以上面的查询等价于:
{
“match”: {
“message”: {
“query”: “this is a test”,
“type”: “phrase”
}
}
}
短语查询根据一个可配置的slop(默认为0)匹配索引词
可以设置analyzer控制在文本上执行的分词器,默认是字段映射中定义的分析器,或者是默认的搜索分析器
{
“match_prase”: {
“message”: {
“query”: “this is a test”,
“analyzer”: “my_analyzer”
}
}
}
3、短语前缀查询
可以对文本最后一个字段进行前缀匹配
{
“match_phrase_prefix”: {
“message”: “this is a test”
}
}
等价于下面的方式:
{
“match”: {
“message”: {
“query”: “this is a test”,
“type”: “phrase_prefix”
}
}
}
短语前缀查询接受和短语查询相同的参数
短语前缀查询接受max_expansions参数,以控制最后索引词会扩展多少前缀。推荐设置为一个可以接受的值来控制查询的执行时间,
4、多字段查询
在标准查询基础上,支持多字段查询,查询指定的字段(多个字段)
{
“multi_match”: {
“query”: “this is a test”,
“fields”: [
“subject”,
“message”
]
}
}
字段支持通配符
{
“multi_match”: {
“query”: “Will Smith”,
“fields”: [
“title”,
“*_name”
]
}
}
个别字段可以用caret(^)符号加权
{
“multi_match”: {
“query”: “this is a test”,
“fields”: [
“subject^3”,
“message”
]
}
}
#subject比message字段重要三倍!
多字段查询内部执行方式由type参数决定,其值如下:
best_fields,默认,查找匹配任何字段的文档,但是使用最佳匹配字段的_score
most_fields,查找匹配任何字段的文档,结合每个字段的_score
cross_fields,用相同的分析器处理字段,将这些字段做为一个大字段,查找任何字段的每个单词
phrase,在每个字段上运行短语匹配查询,结合每个字段的_score
phrase_prefix,在每个字段上运行短语前缀查询,结合每个字段的_score
5、Lucene语法查询
使用语法分析器来分析内容进行查询
{
“query_string”: {
“default_field”: “content”,
“query”: “this AND OR thus”
}
}
query_string为最高级别,查询字符串参数见下表:
(1)默认字段
若在查询语法中没有明确指出查询的字段,会按index.query.default_field提供的字段,默认为_all字段
(2)多字段
query_string查询可以在多个字段上执行,可以通过fields参数定义
多字段执行query_string查询的意义在于利用OR子句扩展每个查询索引词,形如:
field1:query_term OR field2:query_term …
{
“query_string”: {
“fields”: [
“content”,
“name”
],
“query”: “this AND that”
}
}
实际匹配形式为:
{
“query_string”: {
“query”: “(content:this OR name:this) AND (content:that OR name:that)”
}
}
(3)语法
查询字符串被解析为一系列字段和运算符,字段可以是一个单词或者短语(搜索短语中的所有单词,以相同的顺序用双引号包起来)
可用选项有:
1)字段名,可以指定default_field之外的其他字段
#status字段包含active
status:active
#title字段包含quick或brown
title:(quick OR brown)
title:(quick brown)
#author字段包含短语"John Smith"
author:“John Smith”
#任何book.title、book.content或book.date字段包含quick或brown (注意:需要反斜线转义*)
book.*:(quick brown)
#title字段不包含(或者缺失)值
missing:title
#title字段非空
exists:title
2)通配符,?代替单个字符,代替零个或者多个字符
qu?ck bro
3)正则表达式,通过斜线包围,正则表达式可以植入到查询字符串中
name:/joh?n(ath[oa]n)/
4)模糊化
quikc-1
5)邻近搜索,可以指定短语中单词的最大编辑距离
“fox quick”-5
字段中的文本越接近于查询字符串的顺序,文档的相关性越高,短语"quick fox"相似性高于"quick brown fox"
6)范围,日期、数字或字符串字段的范围,包含的范围用方括号指定[min TO max],不包含的范围用花括号指定{min TO max}
#2018年所有日期
date:[2018-01-01 TO 2018-12-31]
#数字1到5
count:[1 TO 5]
#alpha和omega之间的标签,不包含alpah和omega
tag:{alpha TO omega}
#大于等于10的数
count:[10 to ]
#2018年以前的日期
date:{ TO 2018-01-01}
#大于等于1小于5的数
count:[1 TO 5}
#一边值为无限
age:>10 age:>=10 age:<10 age:<=10
7)增权
quick^2 fox
“john smith”^2
(foo bar)^4
8)布尔操作符
- 必须包含
- 必须不包含
支持AND/OR和NOT,也可以写作&&/||和!操作符
((quick AND fox) OR (brown AND fox) OR fox) AND NOT news
上面表达式等同于:
{“bool”:{“must”:{“match”:“fox”},“should”:{“match”:“quick brown”},“must_not”:{“match”:“news”}}}
9)分组,多字段或子句可以使用圆括号进行分组
status:(active OR pending) title:(full text search)^2
10)保留字符,查询中出现保留字符时,需要进行转义
(1+1)=2
保留字符有:±=&&||<>!()[]{}^"~?😕
11)空查询,如果查询字符串为空或仅包含空格时,查询会生成一个空结果集
6、简化查询
简化语法,简化查询不会抛出异常,且会丢弃查询无效部分
{
“simple_query_string”: {
“query”: ““fried eggs” +(eggplant | potato) -frittata”,
“analyzer”: “snowball”,
“fields”: [
“body^5”,
“_all”
],
“default_operator”: “and”
}
}
简化查询可以接受的参数列表:
1)语法
简单查询字符串支持的特殊字符如下:
- 表示AND运算符
| 表示OR运算符
- 排除一个词元
" 包含一批词元来指定搜索短语
- 在索引词结尾表示前缀查询
() 表示优先
~N 在单词的后面,表示编辑距离(模糊性)
~N 在短语的后面,表示溢出量
为搜索任何这些特殊字符,需要使用斜线
2)默认字段
在搜索字符串语法中没有明确指出需要搜索的字段时,index.query.default_field的值用为搜索字段,默认为_all字段
3)多字段
字段参数可以包括基于模式的字段名,可以自动扩展相关字段
{“simple_query_string”:{“fields”:[“content”:“name.*^5”],“query”:“foo bar baz”}}
4.2.3字段查询
全文查询执行前会分析查询字符串,而字段查询会进行精确查询
常用于结构化数据,如数字/日期和枚举
1、单字段查询
查询指定字段中指定内容
{
“term”: {
“user”: “Kimchy”
}
}
2、多字段查询
过滤文档,文档字段匹配任何提供的索引词(不分词)
{
“constant_score”: {
“filter”: {
“terms”: {
“user”: [
“kimchy”,
“elasticsearch”
]
}
}
}
}
3、范围查询
查找某一范围内的内容
Lucene查询类型取决于字段类型,对字符串类型字段,使用TermRangeQuery;对于数字/日期类型字段,使用NumericRangeQuery
{
“range”: {
“age”: {
“gte”: 10,
“lte”: 20,
“boost”: 2
}
}
}
gte:大于或等于
gt:大于
lte:小于或等于
lt:小于
boost:查询加权值,默认为1
2)是否存在查询
查找指定字段包含非空值的文档
{“exists”:{“field”:“user”}}
null,[],[null]为空值
3)为空查询
{“bool”:{“must_not”:{“exists”:{“field”:“user”}}}}
该查询返回user字段没有值的文档
4)前缀查询
查找拥有特定前缀的索引词(不分词),前缀查询对应于lucene中的PrefixQuery
#查询user字段包含以ki开头的索引词的文档
{“prefix”:{“user”:“ki”}}
5)通配符查询
字段匹配通配符表达式(不分词)。匹配任意字符含空字符,?匹配任何单个字符。这种查询可能会比较缓慢,需要在许多索引词上重复执行
为避免极端缓慢的通配符查询,通配符索引词不应该以一个通配符开头。通配符查询对应lucene中的WildcardQuery
{“wildcard”:{“user”:"kiy"}}
6)模糊查询
对字符串型字段使用基于编辑距离的相似性,以及数字型和日期型字段的正负(+/-)范围进行匹配
字符串型字段:
模糊查询基于fuzziness指定的最大编辑距离生成所有可能匹配的索引词,然后检查索引词字典来找出确实存在于索引中的索引词
{“fuzzy”:{“user”:{“value”:“ki”,“boost”:1.0,“fuzziness”:"2,“prefix_length”:0,“max_expansions”:100}}}
参数说明:
fuzziness,最大编辑距离,默认AUTO
prefix_length,不会被模糊化的最初字符数量,可以用来减少必须审查的索引词数量,默认为0
max_expansions,模糊查询将要扩展的索引词最大数量,默认50
数字型和日期型字段:
使用fuzziness值作为范围来执行模糊查询
-fuzziness <= field value <= +fuzziness
{“fuzzy”:{“price”:{“value”:12,“fuzziness”:2}}} #会查询value值范围在10到14之间的结果
{"fuzzy:{“created”:{“value”:“2010-02-05T12:05:07”,“fuzziness”:“1d”}}}
7)类型查询
根据匹配提供的映射类型来过滤文档
{“type”:{“value”:“secilog”}}
8)主键查询
获取只拥有提供的主键的文档,注意,查询使用_uid字段
{“ids”:{“type”:“secilog”,“values”:[“1”,“4”,“100”]}}
type选项是可选的,也可接受数组形式的值,若没有指定类型,所有定义在索引映射中的类型都会被尝试
4.2.4复合查询
复合查询是包含其他叶查询的查询,还可以再包含复合查询,并结合结果和匹配得分来改变它们的行为,或者可以从查询中进行内容过滤
1、常数得分查询
这个查询包含另一个查询,并且仅返回过查询中任何常数得分等于查询加权的文档,对应lucene中的ConstantScoreQuery
{
“constant_score”: {
“filter”: {
“term”: {
“user”: “kimchy”
}
},
“boost”: 1.2
}
}
2、布尔查询
获取匹配其他查询的布尔值的文档,对应lucene的BooleanQuery,基于一个或多个布尔子句的使用,每个子句都有一类事件
must,必须出现在匹配文档中,并且会影响匹配得分
filter,必须出现在匹配文档中,匹配得分会被忽略
should,应该出现在匹配文档中,在布尔查询中如果没有must或filter子句,文档必匹配一个或多个shoud子句。应该匹配的should子句的最小数量可以通过minimum_should_match参数进行设置
must_not,必须不出现在匹配文档中
注意:如果查询用于过滤内容且有should子句,那么最少一个should子句需要被匹配
布尔查询支持disable_coord参数,默认为false
布尔查询采取匹配越多越好的方式,所以每个匹配的must或should子句的得分会被加在一起,提供最终的_score
bool.filter匹配得分
在filter元素下指定的查询对匹配得分没有影响,返回得分为0,得分仅受指定查询的影响
#获取所有status字段包含active索引词的文档
GET secisland/_search
{
“query”: {
“bool”: {
“filter”: {
“term”: {
“method”: “post”
}
}
}
}
}
#该查询对所有文档匹配得分均为0,因为没有指定查询获取匹配得分
GET secisland/_search
{
“query”: {
“bool”: {
“query”: {
“match_all”: {}
},
“filter”: {
“term”: {
“method”: “post”
}
}
}
}
}
#bool不支持query
拥有match_all查询的布尔查询对每个文档指定匹配值为1.0
GET secesland/_search
{
“query”: {
“constant_score”: {
“filter”: {
“term”: {
“method”: “post”
}
}
}
}
}
#constant_score查询对所有通过过滤匹配的文档指定分值1
如果需要知道查询返回的文档匹配布尔查询的哪一条查询子句,可以使用命名查询对每个子句进行命名
3、最大值获取查询
通过执行自己的子查询生成文档的并集,且用文档执行任何子查询的最大匹配得分作为文档得分,对应lucene的DisjunctionMaxQuery
{
“dis_max”: {
“tie_breaker”: 0.7,
“boost”: 1.2,
“queries”: [
{
“term”: {
“age”: 34
}
},
{
“term”: {
“age”: 35
}
}
]
}
}
4、boosting查询
可以用来有效降级匹配给出的查询结果。不像布尔查询的NOT子句,boosting查询仍然选择包含不合需要的索引词的文档,但降低了它们的整体得分
{
“boosting”: {
“positive”: {
“term”: {
“field1”: “value1”
}
},
“negative”: {
“term”: {
“field2”: “value2”
}
},
“negative_boost”: 0.2
}
}
#positive肯定的;negative否定的
5、指定索引查询
当搜索在多个索引中执行时,可以指定索引,通过指定一个索引的列表和一个内部查询,这个内部查询仅在索引名匹配列表时执行,若搜索其它不在列表中的索引时,执行no_match_query
{
“indices”: {
“indices”: [
“index1”,
“index2”
],
“query”: {
“term”: {
“tag”: “wow”
}
},
“no_match_query”: {
“term”: {
“tag”: “kow”
}
}
}
}
可以使用indices字段提供单独的索引。no_match_query可以赋值为none(不匹配任何文档),或者all(匹配所有文档),默认为all
#字段顺序是重要的,indices在query和no_match_query之前提供
6、AND、OR、NOT查询
在其他查询中使用AND、OR、NOT布尔操作符匹配文档
{
“filtered”: {
“query”: {
“term”: {
“name.first”: “shay”
}
},
“filter”: {
“and”: [
{
“range”: {
“postDate”: {
“from”: “2018-03-01”,
“to”: “2018-05-01”
}
}
},
{
“prefix”: {
“name.second”: “ba”
}
}
]
}
}
}
7、过滤查询
过滤查询仅用来过滤结果集,并且另一个集合用来计算匹配得分的查询
#通过过滤尽可能多地排除文档,然后仅在剩下的文档中执行查询
GET secisland/_search
{
“query”: {
“filtered”: {
“query”: {
“match”: {
“method”: “post”
}
},
“filter”: {
“range”: {
“timestamp”: {
“gte”: “now-2d/d”
}
}
}
}
}
}
过滤查询作为query参数的值传递给搜索请求
1)不包含查询的过滤
若不指定查询,默认包含全匹配查询
{
“query”: {
“filtered”: {
“query”: {
“filter”: {
“range”: {
“timestamp”: {
“lte”: “now-2d/d”
}
}
}
}
}
}
}
#没有指定查询,仅过滤,返回过滤后的所有结果
2)多重过滤
多重过滤可以通过包含布尔查询来使用
{“filtered”:{“query”:{“match”:{“secilog”:“full text
search”}},“filter”:{“bool”:{“must”:{“range”:{“created”:{“gte”:"now-1d/d}}},“should”:[{“term”:{“featured”:true}},{“term”:{“starred”:true}}],“must_not”:{“term”:{“deleted”:false}}}}}}
8、限制查询
限制查询限制执行文档(每个分片的)的数量
{
“filtered”: {
“filter”: {
“limit”: {
“value”: 100
}
},
“query”: {
“term”: {
“name.first”: “shay”
}
}
}
}
4.2.5连接查询
在es中执行完整的SQL类型的表关联查询的代价是昂贵的。但es还是提供了两种方式的关联,一种是嵌套,一种是父子关系
1、嵌套查询
嵌套查询可以查询嵌套对象/文档,执行的查询把嵌套对象/文档视作父文档的单独文档
path指出嵌套对象的路径,query查询的范围是在匹配路径的嵌套文档中。任何在查询中引用的字段必须使用全路径
score_mode可以设置内部子匹配如何时影响父匹配得分,默认为avg,也可以为sum/min/max/none
自动支持和检查多级别嵌套,如果内部嵌套查询布在于其他嵌套查询中,会自动匹配相关嵌套级别
2、父/子文档查询
1)子文档查询
将父文档拥有的查询返回匹配到的子文档
{“has_child”:{“type”:“blog_tag”,“query”:{“term”:{“tag”:“something”}}}}
子文档查询支持匹配得分,支持模式有min、max、sum、avg或none,默认值为none,表示产生和前版本相同的行为。
如果得分模式设置为其它值,所有匹配的子文档得分聚合成相关的父文档得分。通过score_mode字段来指定得分类型
{“has_child”:{“type”:“blog_tag”,“score_mode”:“sum”,“query”:{“term”:{“tag”:“something”}}}}
子文档查询可以指定最小或者最大数量的子文档
{“has_child”:{“type”:“blog_tag”,“score_mode”:“sum”,“min_children”:2,“max_children”:10,“query”:{“term”:{“tag”:“something”}}}}
2)父文档查询
在父文档空间执行,通过parent_type指定,返回关联匹配的父文档的子文档。工作方式和子文档查询一样,也接受相同的参数
{“has_parent”:{“parent_type”:“blog”,“query”:{“term”:{“tag”:“something”}}}}
父文档查询支持的得分类型为score或者none,默认为none,忽略从父文档得到的匹配得分,此时,匹配得分基于查询增益,默认是1
如果得分类型设置为score,父文档的匹配得分聚合到属于它的子文档
{“has_parent”:{“parent_type”:“blog”,“score_mode”:“score”,“query”:{“term”:{“tag”:“something”}}}}
4.2.6地理查询
es支持两种类型的地理数据字段:地理点类型,支持经纬度对;地理形状类型,支持点、线、圈、多边形、多边形集合等
1、地理形状查询
地理形状查询使用相同的方格表示为地理形状映射来查找文档,拥有与查询形状相交的形状
查询支持两种方式来定义查询形状,通过提供整个形状定义或引用预索引在其他索引中的形状名
1)形状定义
地理形状过滤使用GeoJSON表示形状
{“query”:{“bool”:{“must”:{“match_all”:{}},“filter”:{“geo_shape”:{“location”:{“shape”:{“type”:“envelope”,“coordinates”:[[13.0,53.0],[14.0,52.0]]},“relation”:“within”}}}}}}
2)预索引形状
查询支持使用存储于其他索引或索引类型中的形状,当存在一个预定义的形状列表时,可以使用逻辑名(如南京)来引用,不需要每次都提供具体的坐标值
这种情况下,需要提供的参数有:
id,包含预索引形状的文档ID
index,预索引形状的索引名,默认为shape
type,预索引形状的索引类型
path,指定的字段作为包含预索引形状的路径,默认为shape
{“bool”:{“must”:{“match_all”:{}},“filter”:{“geo_shape”:{“location”:{“indexed_shape”:{“id”:“EDU”,“type”:“countries”,“index”:“shapes”,“path”:“location”}}}}}}
3)空间关系
所有可以使用的空间关系操作符如下:
INTERSECTS,返回地理形状字段和查询集合相关的所有文档,默认
DISJOINT,返回地理形状字段和查询集合没有关联的所有文档
WITHIN,返回地理形状字段在查询集合内的所有文档
CONTAINS,返回地理形状字段包含查询集合的所有文档
2、地理范围查询
基于一个位置点的范围来过滤查询文档
{“bool”:{“must”:{“match_all”:{}},“filter”:{“geo_bounding_box”:{“pin.location”:{“top_left”:{“lat”:40.73,“lon”:-74.1},“bottom_right”:{“lat”:40.01,“lon”:-71.12}}}}}}
查询选项如下:
_name,可选名称字段来定义过滤请求
ignore_malformed,设置为true来接受无效的经纬度定义的地理点,默认为false
type,设置为indexed或memory,定义过滤会在索引还是内存中执行,默认为memory
接受的格式:
#经纬度作为参数
“filter”:{“geo_bounding_box”:{“pin.location”:{“top_left”:{“lat”:40.73,“lon”:-74.1},“bottom_right”:{“lat”:40.01,“lon”:-71.12}}}}
#经纬度数组
“filter”:{“gep_bounding_box”:{“pin.location”:{“top_left”:[-74.1,40.73],“bottom_right”:[-71.12,40.01]}}}
#经纬度字符串
“filter”:{“geo_bounding_box”:{“pin.location”:{“top_left”:“40.73,-74,1”,“bottom_right”:“40.01,-71,12”}}}
#地理散列
“filter”:{“gep_bounding_box”:{“pin.location”:{“top_left”:“dr5r9ydj2y73”,“bottom_right”:“drj7teegpus6”}}}
地理范围的顶点可以通过top_left、bottom_right或者top_right、bottom_left参数设置,还可以使用top、left、bottom、right分别设置
“filter”:{“top_bounding_box”:{“pin.location”:{“top”:-74.1,“left”:40.73,“bottom”:-71.12,“right”:40.01}}}
3、地理距离查询
获取一个地理点确切距离内的所有文档
{“bool”:{“must”:{“match_all”:{}},“filter”:{“geo_distance”:{“distance”:“200km”,“pin.location”:{“lat”:40,“lon”:-70}}}}}
接受的格式如下
#经纬度作为参数
“filter”:{“geo_distance”:{“distance”:“12km”,“pin.location”:{“lat”:40,“lon”:-70}}}
#经纬度数组
“filter”:{“geo_distance”:{“distance”:“12km”,“pin.location”:[40,-70]}}
#经纬度字符串
“filter”:{“geo_distance”:{“distance”:“12km”,“pin.location”:“40,-70”}}
#地理散列
“filter”:{“geo_distance”:{“distance”:“12km”,“pin.location”:“drm3btev3e86”}}
4、地理距离范围查询
获取在于一个地理点一定距离范围内的所有文档
{“bool”:{“must”:{“match_all”:{}},“filter”:{“geo_distance_range”:{“from”:“200km”,“to”:“400km”,“pin.location”:{“lat”:40,“lon”:-70}}}}}
支持和地理距离过滤相同的位置点参数和查询选项,也支持通用的范围参数:lt,lte,gt,gte,from,to,include_upper,include_lower
5、多边形地理查询
查询可以包含命中多边形内的点
{“bool”:{“query”:{“match_all”:{}},“filter”:{“geo_polygon”:{“person.location”:{“points”:[{“lat”:40,“lon”:-70},{“lat”:30,“lon”:-80},{“lat”:20,“lon”:-90}]}}}}}
接受的格式如下:
#经纬度数组
“filter”:{“geo_polyon”:{“personlocation”:{“points”:[[-70,40],[-80,30],[-90,20]]}}}
#经纬度字符串
“filter”:{“geo_polyon”:{“personlocation”:{“points”:[“40,-70”,“30,-80”,“20,-90”]}}}
#地理散列
“filter”:{“geo_polyon”:{“personlocation”:{“points”:[“drn5xlg8cu2y”,“30,-80”,“20,-90”]}}}
6、地理散列单元查询
提供地理散列层次结构的访问,通过定义地理散列单元,只有单元里的地理点会匹配这个查询
为使过滤生效,所有地理散列前缀需要添加到索引中,如一个地理散列u30需要分解为三个索引词:u30,u3,u,这个分解必须在需要执行过滤的地理字段映射中启用,通过设置geohash_prefix选项:
{“mappings”:{“location”:{“properties”:{“pin”:{“type”:geo_point",“geohash”:true,“geohash_prefix”:true,“geohash_precision”:10}}}}}
地理散列单元可以通过所有格式的地理点定义,如果单元通过经纬度值定义,需要设置单元的大小,通过过滤中的precision参数进行定义,设置一个整数值表示地理散列前缀的长度。除了直接设置地理散列长度,也可以用距离来定义精确度,如"precision":“50m”
{“bool”:{“must”:{“match_all”:{}},“filter”:{“geohash_cell”:{“pin”:{“lat”:13.4080,“lon”:52.5186},“precision”:3,“neighbors”:true}}}}
4.2.7跨度查询
跨度查询是低级别的按位查询,在指定索引词的顺序和接近度上提供专门的控制。通常用于法律或专利文档上执行非常具体的查询
跨度查询不能与非跨度查询混合(多索引词跨度查询例外)1、索引词跨度查询
匹配包含索引词的跨度,对应lucene中的SpanTermQuery
{“span_term”:{“user”:“kimchy”}}
增益也可以关联到查询中:
{“span_term”:{“user”:{“value”:“kimchy”,“boost”:2.0}}}
或者
{“span_term”:{“user”:{“term”:“kimchy”,“boost”:2.0}}}2、多索引词跨度查询
可以封装多索引词查询(任何一个通配符、模糊、前缀、索引词、范围或正则表达式查询)为跨度查询,所以可以被嵌套
{“span_multi”{“match”:{“prefix”:{“user”:{“value”:“ki”,“boost”:1.08}}}}}3、首跨度查询
匹配字段开始附近的跨度,对应lucene中SpanFirstQuery
{“span_first”:{“match”:{“span_term”:{“user”:kimchy"}},“end”:3}}
match子句可以是任何其他类型的跨度查询,end参数控制匹配中允许的最大结束位置4、接近跨度匹配
匹配接近另一个的跨度,可以定义溢出值,表示介于不匹配位置之间的最大值,以及匹配是否按顺序提交请求,对应lucene中SpanNearQuery
{“span_near”:{“clauses”:[{“span_term”:{“field”:“value1”}},{“span_term”:{“field”:"value2}},{“span_term”:{“field”:“value3”}}],“slop”:12,“in_order”:false,“collect_payloads”:false}}
clauses元素是一个或更多其他类型的跨度查询列表
5、或跨度查询
匹配它的跨度子句的并集,对应lucene中SpanOrQuery
{“span_or”:{“clauses”:[{“span_term”:{“field”:“value1”}},{“span_term”:{“field”:"value2}},{“span_term”:{“field”:“value3”}}]}}
clauses元素是一个或更多其他类型的跨度查询列表
6、非跨度查询
移除与另一个跨度查询重叠的匹配,对应lucene中SpanNotQuery
{“span_not”:{“include”:{“span_term”:{“field1”:“boya”}},“exclude”:{“span_near”:{“clauses”:[{“span_term”:{“field1”:“la”}},{“span_term”:{“field1”:“hoya”}}],“slop”:0,“in_order”:true}}}}
include和exclude子句可以是任何类型的跨度查询,include子句的匹配会被过滤掉,exclude子句返回的匹配必须没有重叠的部分
7、包含跨度查询
返回封装另一个跨度查询的匹配,对应lucene中SpanContainingQuery
{“span_containing”:{“little”:{“span_term”:{“field1”:“foo”}},“big”:{“span_near”:{“clauses”:[{“span_term”:{“field1”:“bar”}},{“span_term”:{“field1”:“baz”}}],“slop”:5,“in_order”:true}}}}
big和little子句也以是任何类型的跨度查询,从big匹配的跨度到包含从little返回的匹配
8、内部跨度查询
返回内部封装的另一个跨度查询的匹配,对应lucene中的SpanWithinQuery
{“span_within”:{“little”:{“span_term”:{“field1”:“foo”}},“big”:{“span_near”:{“clauses”:[{“span_term”:{“field1”:"bar}},{“span_term”:{“field1”:“baz”}}],“slop”:5,“in_oorder”:true}}}}
big和little子句可以是任何类型的跨度查询,从little匹配的跨度被封装在big返回的跨度中
4.2.8高亮显示
es的高亮显示来源于lucene,允许一个或多个字段突出显示搜索内容。lucene支持三种高亮显示方式:highlighter、fast-vector-hithlighter、postings-highlighter,highlighter为默认的标准类型
PUT secilog/log/1
{
“type”: “file”,
“message”: “secilog is a log real-time analyse software,it’s full text search is based on Elasticsearch”
}
POST secilog/log/_search
{
“query”: {
“term”: {
“message”: “analyse”
}
},
“highlight”: {
“fields”: {
“message”: {}
}
}
}
#高亮显示使用analyse
为执行高亮显示,该字段需要有实际的内容,且必须进行存储,即字段映射中store值必须为true,不能只在内存中。
系统会自动加载_source字段并匹配相关的列
字段名称支持通配符,如"message*":{} 这将匹配所有message开头的字段
fast-vector-hithlighter
其特点为:
1、快,特别是内容大的字段,比如大于1mb
2、可定制boundary_chars,boundary_max_scan,和fragment_offset
3、可设置term_vector值为with_positions_offsets,增加索引大小
4、可以将多个字段的匹配组合成一个结果
5、可以权重匹配分配在不同的位置上
要实现fast-vector-hithlighter需要映射字段类型
#对content字段采用fast-vector高亮
{“type_name”:{“content”:{“type”:“string”,“term_vector”:“with_positions_offsets”}}}postings-hithlighter
其特点为:
1、快,因为它不需要重新分析文档:尤其是对大文件对性能的提高更为明显
2、占用更少的磁盘空间
3、把高亮显示和句子分开,这个更有利于人类阅读
4、使用BM25算法,使搜索的时候像是整篇文档
要实现postings-hithlighter需要映射字段类型
#对content字段采用postings高亮类型
{“type_name”:{“content”:{“type”:“string”,“index_options”:“offsets”}}}注:高亮查询不支持复杂查询,如match_phrase_prefix
fast-vector-hithlighter和postings-hithlighter会增加索引的大小,但会减少查询的执行时间
使用type字段可以强制使用特定的高亮类型,当设置了term_vectors高亮时,相用普通高亮显示也非常有用。type可设置为三种类型:plain、postings、fvh,分别对应高亮显示的三种类型,如
{
“query”: {
“term”: {
“message”: “analyse”
}
},
“highlight”: {
“fields”: {
“message”: {
“type”: “plain”
}
}
}
}
默认情况下,亮亮显示文本在和中,可以通过设置pre_tags和post_tags进行修改,如
{
“query”: {
“term”: {
“message”: “analyse”
}
},
“highlight”: {
“pre_tags”: [
“”
],
“post_tags”: [
“”
],
“fields”: {
“message”: {
“type”: “plain”
}
}
}
}
可以有多个标签用数组进行表示,按照"重要性"进行排序,如
{
“query”: {
“term”: {
“message”: “analyse”
}
},
“highlight”: {
“pre_tags”: [
“”,
“”
],
“post_tags”: [
“”,
“”
],
“fields”: {
“message”: {
“type”: “plain”
}
}
}
}
系统对有多个pre_tags的情况,需要设置tags_schema为styled,默认post_tags为,默认多个pre_tags标签为,,…
{
“query”: {
“term”: {
“message”: “is”
}
},
“highlight”: {
“tag_schema”: “styled”,
“fields”: {
“message”: {}
}
}
}
每个字段都可以设置高亮显示的字符片fragment_size大小,默认为100,以及返回的最大片段数number_of_fragments,默认5,如果number_of_fragments值设置为0则片段产生,当order设置为score时可以按照评分进行排序,如
{“query”:{…},“highlight”:{“order”:“score”,“fields”:{“content”:{“fragment_size”:150,“number_of_fragments”:3}}}}
4.3简化查询
es提供一套精简API来查看系统状态,官方叫cat API。主要是由于es默认接口返回都是JSON格式,不利于人类阅读,所以搞出cat API进行简化
每个命令都以/_cat开头,可以接受v参数得到详细输出;可以通过help参数得到每列的帮助;可以通过h=参数名返回部分内容,多个参数可以用逗号分开,甚至可以支持通配符
GET http://localhost/_cat/master?v
GET http://localhost/_cat/master?help
可以对系统大部分内部结构进行简化查询,比如索引信息、节点信息,这些内部结构简称指标
1、indices
有非常多的参数,可以用help查看
/_cat/indices?v
/_cat/indices?pri&v&h=health,index,prirep,docs.count,mt
2、nodes
有非常多的参数,可以用help查看
/_cat/nodes?v
/_cat/nodes?v&h=id,ip,port,v,m,jdk
3、recovery
一个集群中,一个索引的分片可能随时会从一个节点迁移到另一个节点,比如在恢复快照的过程中,新节点启动的过程中,等等
/_cat/recovery/secisland?v
通过增加副本节点的数量可以让分片的数据进行传输
4、thread pool
线程池有非常多的参数,可以用help查看
/_cat/thread_pool?v&h=id,host,suggest.active,suggest.rejected,suggest.complete
第五章 聚合
聚合是基于搜索的数据汇总,通过组合可以完成复杂的操作。聚合可以对文档的数据进行统计汇总、分组等。
5.1聚合的分类
通常将聚合分为三大类:
度量聚合:在一组文档中对某一个数字型字段进行计算得出指标值
分组聚合:创建多个分组,每个分组都关联一个关键字和相关文档标准。当聚合执行时,所有分组会根据自身标准评估每一个符合的文档,当文档匹配分组时,会将文档划入相关的分组内。聚合进行完成时,会给出一个分组列表,每个分组都会有一组属于它的文档
管道聚合:这一类聚合的数据源是其他聚合的输出,然后进行相关指标的计算
此外,还可以在分组聚合的基础上添加聚合并执行,即聚合的嵌套,通过嵌套可以完成很多复杂的聚合操作分组聚合可以拥有子聚合(分组聚合或度量聚合),子聚合将计算由父聚合生成的分组,对于聚合嵌套的水平和深度没有硬性限制,可以在一个父聚合下嵌套一个或多个子聚合
聚合的基本结构:
聚合操作用aggregations简写为aggs关键字作为开头,操作的对象是JSON数据结构。
聚合值的数据源,一些聚合针对参与聚合的文档中提取出来的值进行,也可以定义一个脚本,针对每个文档生成这些值
当一个聚合里面同时包含文档字段和脚本时,脚本会被视为值脚本。当使用脚本时,可以定义lang和params,lang定义使用的语言,params表示参数
脚本也可对每个文档生成一个或多个值,当生成多个值时,可以使用script_values_sorted来表明这些值是否需要进行排序。实质上,es处理排序过的值时可以执行优化
5.2度量聚合
度量聚合从文档中提取出来值并进行计算,这些值通常从文档中的字段(数据字段)中提取出来,也可以使用脚本进行计算
数字型度量聚合是一种特殊类型的度量聚合,输出数字类型的值。聚合输出一个数字指示(如平均值聚合)称为单值数字型度量聚合,产生多个指标值(如统计聚合)称为多值数字型度量聚合。当聚合直接作为一些分组聚合的子聚合时,单值和多值度量聚合的内容会发挥巨大作用,如分组聚合可以对度量聚合后的返回值进行排序
平均值聚合
计算平均值
{
“aggs”: {
“avg_grade”: {
“avg”: {
“field”: “grade”
}
}
}
}
POST secisland/_search
{
“aggs”: {
“avg_grade”: {
“avg”: {
“field”: “input”
}
}
}
}
1、脚本
基于脚本计算
POST secisland/_search
{
“aggs”: {
“avg_grade”: {
“avg”: {
“script”: “doc[‘input’].value”
}
}
}
}
#使用文件脚本
{
“aggs”: {
“avg_grade”: {
“avg”: {
“script”: {
“file”: “my_script”,
“params”: {
“field”: “grade”
}
}
}
}
}
}
若需要使用被索引脚本,仅需将file参数替换为id参数
2、文档值脚本
可以对文档中具体某列的值用脚本进行再次计算
{“aggs”:{…“aggs”:{“avg_corrected_grade”:{“avg”:{“field”:“grade”,“script”:{“inline”:“_value*correction”,“params”:{“correction”:1.2}}}}}}}
3、默认值
missing定义文档缺失值时应该如何处理,默认这些文档会被忽略,但也可以设置一个默认值
{“aggs”:{“grade_avg”:{“avg”:{“field”:“grade”,“missing”:10}}}}
当grade字段没有值时,系统会用10作为值进行计算
基数聚合
单值度量聚合,计算不同值的近似计数。值从文档的特定字段提取,也可以通过脚本生成
#统计符合条件的作者author
{“aggs”:{“author_count”:{“cardinality”:{“field”:“author”}}}}
#统计一共有多少个不同的ip
POST secisland/_search {“aggs”:{“author_count”:{“cardinality”:{“field”:“xffip.raw”}}}}
聚合支持precision_threshold选项
{“aggs”:{“author_count”:{“cardinality”:{“field”:“author_hash”,“precision_threshold”:100}}}}
{“aggs”:{“author_count”:{“cardinality”:{“field”:“xffip.raw”,“precision_threshold”:100}}}}
precision_threshold选项允许为了准确性而设置交换内存,并且定义了一种独特的计数。低于计数将接近准确,高于这个值计数可能会变得模糊。最大值为40000,高于40000时,产生的效果与40000相同。默认值取决于创造多分组的父聚合数量
1、计数是近似值
计算精确计数要求加载值到一个哈希集并且返回它的大小,当工作在高基数集时,需要占用大量的内存空间,同时在节点间沟通每个分片集也会占用大量的集群资源,所以计算的效率比较低。基数聚合基于HyperLogLog++算法
2、脚本
基数聚合指标支持脚本,但会带来明显的性能损失
{“aggs”:{“author_count”:{“cardinality”:{“script”:“doc[‘author.first_name’].value+’ '+doc[‘author.last_name’].value”}}}}
{“aggs”:{“input_output”:{“cardinality”:{“script”:“doc[‘input’].value+doc[‘output’]”}}}}
也可以使用文件脚本:
{“aggs”:{“author_count”:{“cadinality”:{“script”:{“file”:“my_script”,“params”:{“first_name_field”:“author.first_name”,“last_name_field”:“author.last_name”}}}}}}
#索引脚本只需要将file参数替换为id参数
3、默认值
missing字段定义了文档缺失值时应如何处理,默认会忽略这些文档,但也可以认为它们有一个默认值存在:
{“aggs”:{“tag_cardinality”:{“cardinality”:{“field”:“tag”,“missing”:“N/A”}}}}
#tag字段中没有内容的文档会划入相同的分组里,这些分组的默认值是N/A
最大值聚合
最大值聚合是一个单值度量聚合,记录和返回从聚合的文档中提取出的数字型值中的最大值
这些值可以从文档中特定数字型字段提取,也可以通过脚本生成
#计算最高价格price
{
“aggs”: {
“max_price”: {
“max”: {
“field”: “price”
}
}
}
}
POST secisland/_search
{
“aggs”: {
“max_input”: {
“max”: {
“field”: “input”
}
}
}
}
1、脚本
{“aggs”:{“max_price”:{“max”:{“script”:“doc[‘price’].value”}}}}
上面这条语句会解释为内联脚本:
{“aggs”:{“max_price”:{“max”:{“script”:{“file”:“my_script”,“params”:{“field”:“price”}}}}}}
索引脚本只需将file参数替换为id参数
2、值脚本
#换算币种之间的汇率
{“aggs”:{“max_price_in_euros”:{“max”:{“field”:“price”,“script”:{“inline”:“_value*conversion_rate”,“patams”:{“conversion_rate”:1.2}}}}}}
最小值聚合
最小值聚合是一个单值度量聚合,记录和返回从聚合的文档中提取出的数字型值中的最小值。这些值可以从文档的特定数字型字段提取,也可以通过脚本生成
#计算最低价格
{“aggs”:{“min_price”:{“min”:{“field”:“price”}}}}
{“aggs”:{“max_input”:{“min”:{“field”:“input”}}}}
和聚合
和聚合是一个单值度量聚合,对聚合文档中提取的数字型进行求和,这些值可以从特定数字型字段提取,也可以通过脚本生成
{“aggs”:{“intraday”:{“sum”:{“field”:“change”}}}}
值计数聚合
值计数聚合是一个单值度量聚合,对聚合文档中提取的值进行计数。这些值可以从文档的特定数字型字段提取,也可以通过脚本生成
{“aggs”:{“grades_count”:{“value_count”:{“field”:“grade”}}}}
{“aggs”:{“max_input”:{“value_count”:{“field”:“input”}}}}
通常情况下,这个聚合会与其他单值聚合一块使用,如在计算平均聚合时,可能也需要知道有多少值参与了平均运算
统计聚合
统计聚合是一个多值度量聚合,对聚合文档提取数字型值进行统计计算,这些值可以从文档特定的数字型字段提取,也可以通过脚本生成
{“aggs”:{“grades_stats”:{“stats”:{“field”:“grade”}}}}
{“aggs”:{“max_input”:{“stats”:{“field”:“input”}}}}
#“count”: 104427,
#“min”: 150,
#“max”: 1248,
#“avg”: 659.397033334291,
#“sum”: 68858854
统计聚合包含:最小值、最大值、和、计数、平均数
百分比聚合
百分比聚合是一个多值度量聚合,对聚合文档中提取的数字型值计算一个或多个百分比。这些值可以从文档的特定数字型字段提取,也可以通过脚本生成
百分比聚合得到的点是在特定比例下出现的观测值,如,95百分比对应值表示这个值大于95%的所有值
百分比聚合常用于寻找极端值,在正态分布中,0.13%和99.87%代表三个标准偏差的平均值,任何落在三个标准偏差之外的数据通常被认为是出现了异常
可以利用百分比聚合的结果评估数据分布,判断数据是否扭曲,分析数据是否符合双峰分布等
#网站加载时间的百分比聚合
{“aggs”:{“load_time_outlier”:{“percentiles”:{“field”:“load_time”}}}}
{“aggs”:{“max_input”:{“percentiles”:{“field”:“input”}}}}
#“1.0”: 617,
#“5.0”: 617,
#“25.0”: 617,
#“50.0”: 673,
#“75.0”: 678,
#“95.0”: 688,
#“99.0”: 688
通常管理员感兴趣的是极端的百分比
{“aggs”:{“load_time_outlier”:{“percentiles”:{“field”:“load_time”,“percents”:[95,99,99.9]}}}}
{“aggs”:{“max_input”:{“percentiles”:{“field”:“input”,“percents”:[95,99,99.9]}}}}
百分比分级聚合
百分比分级聚合是一个多值度量聚合,对聚合文档中提取的数字型值计算一个或多个级别的百分比。这些值可以从文档的特定数字型字段提取,也可以通过脚本生成
百分比等级表示测试值低于某一特定值的百分比,如一个值大于或等于所有测试值的95%,就表示这个值在第95百分比等级
#网站加载时间,规定95%的页面在15ms内完成加载,99%的页面在30ms内完成加载
{“aggs”:{“load_time_outlier”:{“percentlie_ranks”:{“field”:“load_time”,“values”:[15,30]}}}}
{“aggs”:{“max_input”:{“percentile_ranks”:{“field”:“input”,“values”:[600,650]}}}}
#“600.0”: 0.32348885865620347,
#“650.0”: 32.34875328113122
最高命中排行聚合
最高命中排行聚合会在聚合文档中找出相关度最高的文档,这个聚合用来作为子聚合使用,这样每个分组中相关度最高的文档就可以聚合在一起
选项参数:
from 第一个结果的偏移量
size 每个分组返回的命中文档的最大数量,默认返回前三个命中文档
sort 指定最高命中文档应该如何排序,默认情况下按照主查询的分数排序
脚本度量聚合
利用脚本执行的度量聚合,提供一个指标输出
{“query”:{“match_all”:{}},“aggs”:{“profit”:{“scripted_metric”:{“init_script”:“_agg[‘transactions’]=[]”,“map_script”:“if (doc[‘type’.value == “sale”){_agg.transactions.add(doc[‘amount’].value)} else {_agg.transactions.add(-1*doc[‘amount’].value)}”,“combine_script”:“profit =0;for (t in _agg.transactions){profit +=t};return profit”,“reduce_script”:“profit=0;for (a in _aggs){profit+=a};return profit”}}}}
map_script是唯一必要的参数,上面的示例演示了如何使用脚本聚合通过销售和交易成本来计算总利润,可能的响应是"profit":{“value”:170}
也可以指定使用的脚本文件:
{“query”:{“match_all”:{}},“aggs”:{“profit”:{“scripted_metric”:{“init_script”:{“file”:“my_init_script”},“map_script”:{“file”:“my_map_script”},“combine_script”:{“file”:“my_combine_script”},“params”:{“field”:“amount”},“reduce_script”:{“file”:“my_reduce_script”}}}}}
其中init、map和combine脚本的参数必须在全局params对象中指定,这样才可以在脚本间共享参数
1、允许的返回值类型
当一个脚本同时包含多个有效脚本对象时,脚本对象必须返回或存储以下类型的_agg对象:
原始类型;字符串;图(只包含这里列出类型的键和值);数组(只包含这里列出的类型的元素)
2、脚本的作用域
脚本度量聚合的执行有4个阶段:
1)初始化脚本init_script:在任何文档的收集之前执行,允许聚合设置任何初始化状态
2)映射脚本map_script:每个被采集的文档都会执行一次脚本,这是唯一必须要有的脚本。如果没有指定联合脚本combine_script,结果状态需要存储在一个名为_agg的对象中
3)联合脚本combine_script:每个分片会在文档采集结束时执行一次脚本,允许聚合从每个分片中统一状态,如果没有提供联合脚本,联合阶段就会返回聚合变量
4)归纳脚本reduce_script:在所有分片返回结果之后,请求节点执行一次脚本,这个脚本用于访问_aggs变量,_aggs变量是每个分片执行联合脚本之后的结果数组。如果没有提供归纳脚本,归纳阶段会返回_aggs变量
注:page231有对上面脚本的实例分析,分析每个阶段的动作
其他参数说明:
params:可选参数,可以作为参数传递给初始化脚本、映射脚本和联合脚本对象,用于控制聚合行为和存储脚本执行的中间状态,如果没有指定,则提供默认值"params":{“_agg”:{}}
reduce_params:可选参数,可以作为参数传递给归纳脚本的对象,用于控制归纳阶段的行为,如果没有指定,该变量在归纳脚本执行时不会定义
地理边界聚合
地理边界聚合是一个度量聚合,为一个字段计算包含所有地点值的边界框
{“query”:{“match”:{“business_type”:"shop}},“aggs”:{“viewport”:{“geo_bounds”:{“field”:“location”,“wrap_longitude”:true}}}}
#展示查询所有业务类型为商店的文档,并根据文档中位置字段计算出边界框
地理边界聚合指定一个字段用来获得边界
wrap_longitude是可选参数,用于指定边界框是否允许与国际日期变更线重叠,默认为true
地理重心聚合
地理重心聚合是一个度量聚合,从文档的地理点数据类型字段获取的所有坐标值中计算出有利的矩心,注,字段必须是地理点数据类型
{“query”:{“match”:{“crime”:“burglary”}},“aggs”:{“centroid”:{“geo_centroid”:{“field”:“location”}}}}
#查询所有犯罪类型为盗窃的文档,并根据文档中位置字段计算出矩心
地理重心聚合经常作为子聚合与其他分组聚合结合使用
{“query”:{“match”:{“crime”:“burglary”}},“aggs”:{“towns”:{“terms”:{“field”:“town”},“aggs”:{“centroid”:{“geo_centroid”:{“field”:“location”}}}}}}
#用地理重心聚合作为索引分组聚合的子聚合来找出每个城镇中犯盗窃罪最严重的位置
5.3分组聚合
分组聚合不像度量聚合那样通过字段进行计算,而是根据文档创建分组。每个聚合都关联一个标准,决定一个文档是否划入该分组中。分组实际上定义一个文档集,将文档分组,并计算每组文档的数量
分组聚合可以拥有子聚合,子聚合将父聚合的分组进一步细分
子聚合
子聚合是一个特殊的单分组聚合,通过父类型文档的分组聚合产生子类型的分组。子聚合依赖映射中的_parent字段,只有一个选项type,表示父空间的分组应该被映射为哪种子类型
#假如有一个包含问题和答案两个类型的文档的索引,答案类型有_parent字段:{“answer”:{“_parent”:{“type”:question"}}}
#问题类型文档拥有一个标签字段,答案类型文档拥有一个所有者字段。两个字段分别存在于两个不同类型的文档中,通过子聚合可以把一个问题类型的标签分组映射到答案类型文档的所有者分组
{“aggs”:{“top-tags”:{“terms”{“field”:“tags”,“size”:10},“aggs”:{“to-answers”:{“children”:{“type”:“answer”},“aggs”:{“top-names”:{“terms”:{“field”:“owner.display_name”,“size”:10}}}}}}}}
type指向名为answer的类型/映射
直方图聚合
直方图聚合是一个多分组聚合,可以应用于从文档中提取的数值。在数值上动态创建固定大小(区间)的分组。将数值放入固定区间的分组中,取整算法为:
rem = value % interval
if (rem<0) {rem += interval}
bucket_key =value - rem
#间隔interval必须为整数,分组前数值会被转换为整数,这会造成负浮点数划分分组时的右移问题
{“aggs”:{“prices”:{“histogram”:{“field”:“price”,“interval”:50}}}}
POST secisland/_search {“aggs”:{“input-value”:{“histogram”:{“field”:“input”,“interval”:“50”}}}}1、最小文档计数
默认的,响应会用空分组填补直方图的空白区间,可以利用min_doc_count设置来修改分组,用以过滤掉空区间
{“aggs”:{“input-value”:{“histogram”:{“field”:“input”,“interval”:“50”,“min_doc_count”:1}}}}
默认情况下,直方图返回的分组的范围基于数据本身,即数据中最大值和最小值决定了区间的两个边界,当请求空分组时,会导致混乱,特别是在数据被过滤的情况下,即过滤的范围超出了边界时
extended_bounds可以强制直方图聚合从指定的最小值开始,只有min_doc_count参数为0时,extended_bounds参数才有意义,min_doc_count大于0时,永远不会返回空区间
当extended_bounds.min比文档的值还大时,依然会正常创建分组
{“query”:{“constant_score”:{“filter”:{“range”:{“price”:{“to”:500}}}}},“aggs”:{“prices”:{“histogram”:{“field”:“price”,“interval”:50,“extended_bounds”:{“min”:0,“max”:500}}}}}2、排序
返回的分组默认按照它们的键升序排序,当然,也可以通过order来控制排序行为
#通过分组键排序-降序
{“aggs”:{“prices”:{“histogram”:{“field”:“price”,“interval”:50,“order”:{“_key”:“desc”}}}}}
{“aggs”:{“input-value”:{“histogram”:{“field”:“input”,“interval”:“50”,“order”:{“_key”:“desc”}}}}}
#通过分组键排序-升序
{“aggs”:{“prices”:{“histogram”:{“field”:“price”,“interval”:50,“order”:{"cunt":“asc”}}}}}
{“aggs”:{“input-value”:{“histogram”:{“field”:“input”,“interval”:“50”,“order”:{"count":“asc”}}}}}
#如果直方图聚合有一个直接的指标子聚合,后者可以决定分组的排序方式
{“aggs”:{“prices”:{“histogram”:{“field”:“price”,“interval”:50,“order”:{“price_stats.min”:“asc”}},“aggs”:{“price_stats”:{“stats”:{}}}}}}
排序参数"price_stats.min":“asc"会根据名为price_stats的子聚合里的min值对分组进行排序
不需要为price_stats聚合配置价格字段,它会默认从直方图爷聚合中继承3、偏移
分组的区间默认从0开始然后以interval的值为间隔步进,可以使用offset选项来改变分组的范围
日期直方图聚合
日期直方图聚合是一个多分组聚合,只能应用于日期型的值
主要是解决时间间隔的不固定问题(每个月的天数不固定)
{“aggs”:{“articles_over_time”:{“date_histogram”:{“field”:“date”,“interval”:“month”}}}}
可用的间隔表达式有:year/month/week/day/hour/quarter/minute/second1、时间键值
指定日期格式
{“aggs”:{“articles_over_time”:{“date_histogram”:{“field”:“date”,“interval”:“1M”,“format”:“yyyy-MM-dd”}}}}
返回结果中会不key和key_as_string,前者为Unix时间戳,后者为格式化的时间2、时间区间
默认时间为UTC,可以通过time_zone设置时区,可以为+08:00或者America/Los_Angeles两种格式
{“aggs”:{“by_day”:{“date_histogram”:{“field”:“date”,“interval”:“day”,“time_zone”:”+08:00"}}}}3、偏移
offset参数通过±偏移来修改每个分组的时间起始值,1h代表1小时,1M代表1个月
{“aggs”:{“by_day”:{“date_histogram”:{“field”:“date”,“interval”:“day”,“offset”:“+6h”}}}}
时间范围聚合
时间范围聚合是专门用于时间型数据的范围聚合,与普通范围聚合区别在于from和to参数值可以使用日期数学表达式,也可以指定返回的from和to字段的日期格式。
时间范围聚合在每个范围内包含from但不包含to
{“aggs”:{“range”:{“date_range”:{“field”:“date”,“format”:“MM-yyyy”,“ranges”:[{“to”:"now-10M/M},{“from”:“now-10M/M”}]}}}}
范围聚合
范围聚合是基于多组值来源的聚合,由用户定义一系列范围,每个范围代表一个分组
范围聚合的边界范围包含from,但不包含to
{“aggs”:{“price_ranges”:{“range”:{“field”:“price”,“ranges”:[{“to”:50},{“from”:50,"to"100},{“from”:100}]}}}}
{“aggs”:{“web-input”:{“range”:{“field”:“input”,“ranges”:[{“to”:10}]}}}} #小于10的
– from – to —> from在左边,to在右边
过滤聚合
过滤聚合是一个单分组聚合,包含当前文档中所有匹配指定过滤条件的文档,常用于从当前聚合中得到一个具体的文档集
{“aggs”:{“red_products”:{“filter”:{“term”:{“color”:“red”}},“aggs”:{“avg_price”:{“avg”:{“filed”:“price”}}}}}}
#计算所有红色产品的平均价格
{“aggs”:{“post-method”:{“filter”:{“term”:{“method”:“post”}},“aggs”:{“avg_input”:{“avg”:{“field”:“input”}}}}}}
多重过滤聚合
多重过滤聚合定义一个多分组聚合,每个分组关联一个过滤条件,收集所有满足过滤条件的文档
{“aggs”:{“messages”:{“filters”:{“filters”:{“errors”:{“term”:{“body”:“error”}},“warnings”:{“term”:{“body”:“warning”}}}},“aggs”:{“monthly”:{“histogram”:{“field”:“timestamp”,“interval”:“1M”}}}}}}
#创建两个关于日志数据的分组,一个收集包含错误信息的文档,另一个收集包含警告信息的文档,且每个分组会按月份划分1、匿名过滤
过滤字段可以作为过滤数组提供,经过过滤生成的分组会以请求的顺序返回2、其他分组
设置other_bucket参数可以在响应中添加一个分组,用来收集所有没有匹配到任何给定过滤条件的文档。接受false和true,false表示不计算其他分组,true表示返回other分组,如果是命名过滤聚合,该分组会默认命名为_other,如果是匿名过滤聚合,该分组会作为最后一个返回
other_bucket_key参数可以修改默认的名称_other,设置该参数即认为other_bucket为true
{“aggs”:{“messages”:{“filters”:{“other_bucket_key”:“other_messages”,“filters”:{“error”:{“term”:{“body”:“error”}},“warning”:{“term”:{“body”:“warning”}}}},“aggs”:{“monthy”:{“histogram”:{“field”:“timestamp”,“interval”:“1M”}}}}}}
空值聚合
空值聚合是一个基于字段数据的单分组聚合,对所有缺失字段值(字段值为空或者为null)的文档创建一个分组。通常和其他字段数据分组聚合一起使用,返回由于缺少字段值而不能放入其他任何分组中的所有文档的信息
{“aggs”:{“products_without_a_price”:{“missing”:{“field”:"price}}}}
POST secisland/_search {“aggs”:{“miss-input”:{“missing”:{“field”:“input”}}}}
嵌套聚合
嵌套聚合是一种特殊的单分组聚合,可以聚合嵌套的文档
嵌套聚合需要定义嵌入文档在顶级文档中的路径,可以在嵌入文档上定义任何类型的聚合
采样聚合
采样聚合是一个过滤聚合,用于子聚合限制得分最高的文档的样本。不同的设置可以用于限制共享一个共同值匹配的数量,如"作者"
使用环境:
重点分析高相关性的匹配而不是包含一大堆低质量的匹配
移除分析中的偏差以确保从不同来源获取内容的公平性
为减少聚合运行的成本,通过significant_tems只处理有用的结果
{“query”:{“match”:{“text”:“iphone”}},“aggs”:{“sample”:{“sampler”:{“shard_size”:200,“field”:“user.id”},“aggs”:{“keywords”:{“significant_terms”:{“field”:“text”}}}}}}
#每个分片只抽取200个结果,significant_terms聚合的结果不会被任何单一过度活跃的用户影响1、分片规模
shard_size参数限制每个分片执行采样的过程中多少高得分文档会被采集,默认值为1002、控制差异
可以任意使用字段或者脚本以及max_doc_per_value来控制任何分片采集具有相同值的文档的最大数量,值的选择来自于一个固定的字段或者由一个脚本动态派生
如果选择的字段或脚本为一个文档生成了多个值,聚合会报错3、字段
利用字段控制差异
{“aggs”:{“sample”:{“sampler”:{“field”:“author”,“max_docs_per_value”:3}}}}
max_docs_per_value设置只为分片局部采样的目的应用在每个分片的基础上,不作为在整体搜索结果上提供去重功能的方法4、脚本
利用脚本控制差异
{“aggs”:{“sample”:{“sampler”:{“script”:“doc[‘author’].value+‘/’+doc[‘genre’].value”}}}}
#使用max_docs_per_value的默认值1以结合author和genre字段来确保每个分片采集的样本最多有一个匹配author/genre对
重要索引词聚合
重要索引词聚合返回一组索引词中令人关注或不同寻常的事件
使用示例:
当用户在文本中搜索"禽流感"时,给出建议"H5N1"
从信用卡交易历史报告中,分析持卡人损失,从而确认商户共同特性
指出爆胎率超标的轮胎厂商1、单一分析
最简单的情况下,前台集是匹配查询条件的搜索结果,用于统计对比的后台集是聚合结果的索引
{“query”:{“terms”:{“force”:[“British Transport Police”]}},“aggregations”:{“significantCrimeTypes”:{“significant_terms”:{“field”:“crime_type”}}}}
#查询所有警察机关的犯罪指数,结果发现自行车盗窃案的比例不符合预期
寻找异常的犯罪类型2、多重分析
执行跨多个类别分析的简单方法,利用父级聚合来划分数据
{“aggregations”:{“forces”:{“terms”:{“field”:“force”},“aggregations”:{“significantCrimeTypes”:{“significant_terms”:{“field”:“crime_type”}}}}}}
索引词聚合
索引词聚合是一个基于聚合产生一个多组的值,每个分组都是由一个独特的值动态创建,类似于词云
{“aggs”:{“terms”:{“terms”:{“field”:“collectType”}}}}
POST secisland/_search {“aggs”:{“terms”:{“terms”:{“field”:“agent.raw”}}}}
在返回结果中:
doc_count_error_upper_bound代表每个索引词文档计数的错误上限
当存在大量不同索引词时,es只返回排名靠前的索引词
sum_other_doc_count代表所有没有在响应中分组里的文档计数之和
默认,索引词通过文档计数doc_count排序,条件聚合会返回前10的索引词生成的分组,可以通过设置size参数对返回结果的数量进行修改
{“aggs”:{“terms”:{“terms”:{“size”:20,“field”:“agent.raw”}}}}
1、规模
通过设置size参数,可以定义需要返回的索引词分组的数量。默认,协调搜索进程的节点会请求每个分片提供顶层与规模大小相同的索引词分组,当所有分片响应完成时,节点会缩小最终结果的规模并返回给用户。这意味着如果不同索引词的数量大于规模,返回的列表会发生偏移和失真
如果规模设置为0,规模的大小会是Integer.MAX_VALUE
2、排序
通过设置order参数,可以自定义分组的排序方式。默认,分组根据doc_count参数降序排序
#根据分组doc_count升序排序
{“aggs”:{“genders”:{“terms”:{“field”:“gender”,“order”:{“_count”:“asc”}}}}}
#根据分组索引词字母顺序升序排序
{“aggs”:{“genders”:{“terms”:{“field”:“gender”,“order”:{“_term”:“asc”}}}}}
#通过单值指标子聚合排序(通过聚合名称进行定义)
{“aggs”:{“genders”:{“terms”:{“field”:“gender”,“order”:{“avg_height”:“desc”}},“aggs”:{“avg_height”:{“avg”:{“field”:“height”}}}}}}
#通过多值指标子聚合进行排序(通过聚合名称进行定义)
{“aggs”:{“genders”:{“terms”:{“field”:gender",“order”:{“height_stats.avg”:“desc”}},“aggs”:{“height_stats”:{“stats”:{“field”:“height”}}}}}}
无论聚合路径上最后一个聚合是单分组还是多分组,只要聚合路径是一个单分组类型,就可以基于更“深”一层的聚合对分组进行排序
单分组类型排序会基于分组里文档的数字进行,多组类型应用相同的规则
路径的定义:
聚合分隔符为>
指标分隔符为.
聚合名为<聚合的名称>
指标为<指标的名称(如果是多值度量聚合)>
路径为<聚合名>[<聚合分隔符><聚合名>][<指标分隔符><指标>]
{“aggs”:{“countries”:{“terms”:{“field”:“address.country”,“order”:{“females>height_stats.avg”:“desc”}},“aggs”:{“females”:{“filter”:{“term”:{“gender”:“female”}},“aggs”:{“height_stats”:{“stats”:{“field”:“height”}}}}}}}}
#基于女性人群的平均身高对国家这个指标进行排序
可以通过提供排序标准的数组,利用多个排序标准对分组进行排序:
{“aggs”:{“countries”:{“terms”:{“field”:“address.country”,“order”:[{“females>height_stats.avg”:“desc”},{"count":“desc”}]},“aggs”:{“females”:{“filter”:{“term”:{“gender”:{“female”}}},“aggs”:{“height_stats”:{“stats”:{“field”:“height”}}}}}}}}
如果两个分组在所有排序标准下拥有相同的值,将用分组的索引词进行首字母升序排序,确保分组排序一致性
3、过滤值
可以使用include和exclude对创建分组的索引词进行过滤,该过程基于正则表达式的字符串或一组精确值
{“aggs”:{“tags”:{“terms”:{“field”:“tags”,“include”:[“mazda”,“honda”],“exclude”:"water."}}}}
#include确定哪些值被聚合;exclude确定哪些值不能被聚合。exclude具有优化权,因此,同时包含include和exclude的索引词会被忽略
4、多字段索引词聚合
索引词聚合不支持在同一类型文档的多个字段中采集索引词,原因是索引词聚合不采集字符串索引词自身的值,而是利用全局序数来生成一个字段中所有唯一值的列表。全局序数可以提升性能,但不能跨多个字段
下面两个方式可以用于在多个字段上执行索引词聚合:
脚本,利用脚本在多个字段上重复进行索引词聚合,但会使全局序数优化失效,速度会更慢
copy_to字段,可以在映射中用copy_to创建一个专用字段包含这些字段的值,然后在这个字段上执行聚合,且不会影响全局序数的优化效果
5、采集模式
当字段拥有很多不同的索引词但必要的结果却很少时,可以在上层父聚合精简之后再执行子聚合的计算,这样会更有效率。
通常,聚合树的分支会优先在深度上扩展,然后才会进行精简,这在一些特殊情况下,会非常浪费系统资源且会受到内存的限制
#查询一个电影数据库,找出10个最受欢迎的演员和他们最常合作的5个演员
{“aggs”:{“actors”:{“terms”:{“field”:“actors”,“size”:10},“aggs”:{“costars”:{“terms”:{“field”:“actors”,“size”:5}}}}}}
#上面查询更优化的方案是:
{“aggs”:{“actors”:{“terms”:{“field”:“actors”,“size”:10,“collect_mode”:“breadth_first”},“aggs”:{“costars”:{“terms”:{“field”:“actors”,“size”:5}}}}}}
当使用广度优先模式时,落入最上分组里的文档会被缓存以便随后复用。通常,默认的深度优先采集模式是最好的选择,但在某此特殊情况下,广度优先会效率显著
使用广度优先采集模式时,不可以在聚合中嵌入top_hits这种需要访问匹配得分信息的聚合,因为这么做需要缓存每个文档的浮点得分值,会造成非常昂贵的内存开销
总体聚合
总体聚合是在搜索执行的环境中定义一个包含所有文档的单分组,环境被搜索的索引和文档类型定义,不受搜索查询本身的影响
总体聚合只能作为顶级聚合使用,因为把总体聚合嵌入其他分组聚合中是没有意义的
{“query”:{“match”:{“title”:“shirt”}},“aggs”:{“all_products”:{“global”:{},“aggs”:{“avg_price”:{“avg”:{“field”,“price”}}}}}}
{“query”:{“match”:{“method”:“post”}},“aggs”:{“all_input”:{“global”:{},“aggs”:{“avp_input”:{“avg”:{“field”:“input”}}}}}} #会多一个文档总数字段
总体聚合的聚合体是空的
地理点距离聚合
作用于地理点类型字段上面的多组聚合,原理和范围聚合非常像。用户可以定义一个原点和一系列距离范围分组。聚合评估每个文档的值和原点之间的距离,然后基于范围决定文档属于哪个分组
{“aggs”:{“rings_around_amsterdam”:{“geo_distance”:{“field”:“location”,“origin”:“52.3760,4.894”,“ranges”:[{“to”:100},{“from”:100,“to”:300},{“from”:300}]}}}}
所指定的字段必须是地理点类型(在映射中明确设置)。也可以定义一个地理点类型的字段数组,在聚合期间会考虑所有字段。原点参数可以接受所有地理点类型支持的格式
对象格式:{“lat”:52.3760,“lon”:4.894},最安全的格式
字符串格式:“52.3760,4.894”,第一个代表纬度,第二个代表经度
数组格式:[4.894,52.3760],基于GeoJSON标准,第一个数字代表经度,第二个数字代表纬度
默认距离的单位是米metres,也可以接受其他距离单位:英里miles,英寸inches,码yards,千米kilometers,厘米centimeters,毫米millimeters
{“aggs”:{“rings”:{“geo_distance”:{“field”:“location”,“origin”:“52.3760,4.894”,“unit”:“mi”,“ranges”:[{“to”:100},{“from”:100,“to”:300},{“from”:300}]}}}}
有三种距离计算模式:sloppy_arc默认,arc最精确,plane最快,可使用distance_type参数设置
地理散列网格聚合
作用于地理点类型字段上的多组聚合,将各个点分配到代表网格中各个单元格的分组里。聚合结果网格可能很稀疏,且只包含匹配到数据的单元格,每个单元格复用自定义精度下产生的地理散列值进行标记,其特点有:
高精度地理散列字符串长度很长且每个网格覆盖很小的地理区域
低精度地理散列字符串长度比较短且每个网格覆盖很大的地理区域
这个聚合使用的地理散列有精度选择,1至12,默认精度是5
#以精度12创建的网格,覆盖的面积小于一平方米,会有非常高的内存开销,结果的体积也会非常大1、简单的低精度请求
{“aggregations”:{“myLarge-GrainGeoHashGrid”:{“geohash_grid”:{“field”:“location”,“precision”:3}}}}2、高精度请求
{“aggregations”:{“zoomedInView”:{“filter”:{“geo_bounding_box”:{“location”:{“top_left”:“51.73,0.9”,“bottom_right”:“51.55,1.1”}}},“aggregations”:{“zoom1”:{“geohash_grid”:{“field”:“location”,“precision”:8}}}}}}3、在赤道上单元格的面积
单元格面积随着纬度的增大而变小,赤道上是最大的
IPv4范围聚合
像专用的日期范围聚合一样,IPv4范围聚合专用于IPv4类型字段
{“aggs”:{“ip_ranges”:{“ip_range”:{“field”:“ip”,“ranges”:[{“to”:“10.0.0.5”},{“from”:“10.0.0.5”}]}}}}
IP范围也可以用CIDR掩码来定义
{“aggs”:{“ip_ranges”:{“ip_range”:{“field”:“ip”,“ranges”:[{“mask”:“10.0.0.0/25”},{“mask”:“10.0.0.127/25”}]}}}}
5.4管道聚合
管道聚合利用其他聚合产生的结果,不是文档集,用于向输出树添加信息
分类:
父类聚合:在父聚合输出结果的基础上进行管道聚合,可以在现有分组上计算新的分组或聚合
兄弟聚合:在兄弟聚合输出结果的基础上进行管道聚合,可以计算与兄弟聚合相同等级的新聚合
通过buckets_path参数指定请求批标的路径,管道聚合可以引用需要的聚合来执行计算
管道聚合不能拥有子聚合,但可以在buckets_path参数中引入另一个管道聚合,使管道聚合链接起来1、buckets_path语法
大多数管道聚合需要另一个聚合作为它的输入,输入聚合通过buckets_path参数定义,格式为:
聚合分隔符为>
指标分隔符为.
聚合名为<聚合的名称>
指标名为<指标的名称(如果是多值度量聚合)>
路径为<聚合名>[<聚合分隔符><聚合名>]*[<指标分隔符><指标>]
如my_bucket>my_stats.avg会将my_stats中平均值指标作为my_bucket分组聚合的输入
路径跟管道聚合的位置是相对的,并不是绝对路径,路径不能沿聚合树向上返回
#在日期直方图聚合中嵌入移动平均值聚合,并指出兄弟聚合指标the_sum
{“my_date_histo”:{“date_histogram”:{“field”:“timestamp”,“interval”:“day”},“aggs”:{“the_sum”:{“sum”:{“field”:“lemmings”}},“the_movavg”:{“moving_avg”:{“backets_path”:“the_sum”}}}}}
#buckets_path通过相对路径the_sum指出聚合指标
buckets_path也用于兄弟管道聚合,管道聚合"靠近"一系列分组聚合而不是嵌入它们里面
#max_bucket聚合利用buckets_path指定一个嵌入兄弟聚合的指标
{“aggs”:{“sales_per_month”:{“date_histogram”:{“field”:“date”,“interval”:“month”},“aggs”:{“sales”:{“sum”:{“field”:“price”}}}},“max_monthly_sales”:{“max_bucket”:{“buckets_path”:“sales_per_month>sales”}}}}2、特殊路径
buckets_path可以使用特殊的_count路径,让管道聚合使用文档计数作为输入参数。
#移动平均值聚合可以计算每个分组的文档计数而不是给出具体的指标
{“my_date_histo”:{“date_histogram”:{“field”:“timestamp”,“interval”:“day”},“aggs”:{“the_movavg”:{“moving_avg”:{“buckets_path”:“_count”}}}}}3、处理空数据
缺口策略是用来通知管道聚合当遭遇到数据缺口时应该执行哪种行为的机制。所有的管道聚合都支持gap_policy参数指定缺口策略,有两种缺口策略可以选择:
路过(skip),将缺失数据分组视为不存在,会跳过这个分组并使用下一个可用值继续计算
插入零值(insert_zeros),用零替代缺失值,管道聚合会照常计算
平均分组聚合
平均分组聚合会计算在一组聚合中指定指标的平均值。指定的指标必须是数字型而且这个组聚合必须是多组聚合。用avg_bucket表示
{“avg_bucket”:{“buckets_path”:“the_sum”}}
参数如下:
buckets_path,想要计算平均值的分组路径
gap_policy,缺口策略,默认为跳过
format,用于规范聚合输出值的格式,默认为null
#计算每月销售总额的平均值
{“aggs”:{“sales_per_month”:{“date_histogram”:{“field”:“date”,“interval”:“month”},“aggs”:{“sales”:{“sum”:{“field”:“price”}}}},“avg_monthly_sales”:{“avg_bucket”:{“buckets_path”:“sales_per_month>sales”}}}}
移动平均聚合
给出一组有序的数据,移动平均聚合会在数据上滑动一个固定大小的窗口并计算窗口的平均值
移动平均值是对数据序列进行平滑处理的简单方法,常用于基于时间的数据,如股票价格或服务指标,平滑可以用来消除高频波动或者随机噪声,使低频趋势变得更加容易发现
用moving_avg表示移动平均聚合
{“moving_avg”:{“buckets_path”:“the_sum”,“model”:“holt”,“window”:5,“gap_policy”:“insert_zero”,“settings”:{“alpha”:0.8}}}
参数如下
buckets_path,指标路径
model,使用的移动平均加权模型
gap_policy,缺口策略,默认插入零值
window,滑动的窗口大小,默认为5
settings,模型的具体设置,不同的模型有不同的内容
移动平均聚合必须嵌入到一个直方图或者日期直方图聚合中使用
{“my_date_histo”:{“date_histogram”:{“field”:“timestamp”,“interval”:“day”},“aggs”:{“the_sum”:{“sum”:{“field”:“lemmings”}},“the_movavg”:{“moving_avg”:{“buckets_path”:“the_sum”}}}}}
可以在直方图聚合里随意加入普通的度量聚合,最后把移动平均聚合嵌入到直方图中,然后buckets_path参数指出一个直方图聚合中的兄弟度量聚合
总和分组聚合
总和分组聚合用于计算一组聚合创建的所有分组中指定指标的和。指定的指标必须是数字型且这个组聚合必须是多组聚合
用sum_bucket表示
{“sum_bucket”:{“buckets_path”:“the_sum”}}
#计算所有月销售总额sales分组的和
{“aggs”:{“sales_per_month”:{“date_histogram”:{“field”:“date”,“interval”:“month”},“aggs”:{“sales”:{“sum”:{“field”:“price”}}}},“sum_monthly_sales”:{“sum_bucket”:{“buckets_path”:“sales_per_month>sales”}}}}
总和累计聚合
总和累计聚合父管道聚合,计算父直方图(或日期直方图)聚合中指定的指标的累计值,指定的指标必须是数字型且直方图聚合必须设置min_doc_count为0
用cumulative_sum表示总和累计聚合
{“cumulative_sum”:{“buckets_path”:“the_sum”}}
#计算所有月销售总额sales分组的累计和
{“aggs”:{“sales_per_month”:{“date_histogram”:{“field”:“date”,“interval”:“month”},“aggs”:{“sales”:{“sum”:{“field”:“price”}},“cumulative_sales”:{“cumulative_sum”:{“buckets_path”:“sales”}}}}}}
最大分组聚合
最大分组聚合所定义的分组包含一组聚合指定指标的最大值,且同时输出分组的键和值。指定的指标必须是数字型且这个组聚合必须是多组聚合
用max_bucket表示最大分组聚合
{“max_bucket”:{“buckets_path”:“the_sum”}}
#计算所有月份销售总额的最大值
{“aggs”:{“sales_per_month”:{“date_histogram”:{“field”:“date”,“interval”:“month”},“aggs”:{“sales”:{“sum”:{“field”:“price”}}}},“max_monthly_sales”:{“max_bucket”:{“buckets_path”:“sales_per_month>sales”}}}}
最小分组聚合
最小分组聚合所定义的分组包含一组聚合指定指标的最小值,并且同时输出分组的键和值。指定的指标必须是数字型且这个组聚合必须是多组聚合
用min_bucket表示最小分组聚合
{“min_bucket”:{“buckets_path”:“the_sum”}}
#计算所有月份销售总额的最小值
{“aggs”:{“sales_per_month”:{“date_histogram”:{“field”:“date”,“interval”:“month”},“aggs”:{“sales”:{“sum”:{“field”:“price”}}}},“min_monthly_sales”:{“min_bucket”:{“bucket_path”:“sales_per_month>sales”}}}}
统计分组聚合
统计分组聚合,在一组聚合的所有分组中对一个指标计算各种统计值。指定的指标必须是数字型,且这个组聚合必须是多组聚合
用stats_bucket表示统计分组聚合
{“stats_bucket”:{“buckets_path”:“the_sum”}}
#计算所有月份销售总额的统计值
{“aggs”:{“sales_per_month”:{“date_histogram”:{“field”:“date”,“interval”:“month”},“aggs”:{“sales”:{“sum”:{“field”:“price”}}}},“stats_monthly_sales”:{“stats_bucket”:{“buckets_path”:“sales_per_month>sales”}}}}
返回count/min/max/avg/sum的值
百分位分组聚合
百分位分组聚合是在一组聚合的所有分组中对一个指定的指标计算百分比。指定的指标必须是数字型且这个组聚合必须是多组聚合
用percentiles_bucket表示百分比分组聚合
{“percentiles_bucket”:{“buckets_path”:“the_sum”}}
#对所有月份的销售总额进行百分比计算
{“aggs”:{“sales_per_month”:{“date_histogram”:{“field”:“date”,“interval”:“month”},“aggs”:{“sales”:{“field”:“price”}}}},“sum_monthly_sales”:{“percentiles_bucket”:{“buckets_path”:{“sales_per_month>sales”,“percints”:[25.0,50.0,75.0]}}}}
差值聚合
差值聚合是计算一个指定的指标在两个分组之间的差值。指定的指标必须是数字型且必须设置直方图min_doc_count参数为0
用derivative表示差值聚合
{“derivative”:{“buckets_path”:“the_sum”}}1、一级差值
#计算所有月份销售总额的差值
{“aggs”:{“sales_per_month”:{“date_histogram”:{“field”:“date”,“interval”:“month”},“aggs”:{“sales”:{“sum”:{“field”:“price”}},“sales_deriv”:{“derivative”:{“buckets_path”:“sales”}}}}}}
需要至少两个数据点才有差值,所以返回的结果中第一个分组没有差值
差值单位默认和sales聚合以及父直方图相同2、二级差值
可以把差值管道聚合链接到另一个差值管道聚合的结果上,计算二级差值
{“aggs”:{“sales_per_month”:{“date_histogram”:{“field”:“date”,“interval”:“month”},“aggs”:{“sales”:{“sum”:{“field”:“price”}},“sales_deriv”:{“derivative”:{“buckets_path”:“sales”}},“sales_2nd_deriv”:{“derivative”:{“buckets_path”:“sales_deriv”}}}}}}
二级差值聚合的参数buckets_path指向一级差值,一级聚合产生两个差值后,才会产生二级聚合的值
3、单位
差值聚合中,差值的单位是可以指定的,在响应中会返回一个额外的字段normalized_value,汇报在x轴单位下的差值
#计算每个月的销售额的差值,但差值单位是每天的销售总额
{“aggs”:{“sales_per_month”:{“date_histogram”:{“field”:“date”,“interval”:“month”},“aggs”:{“sales”:{“sum”:{“field”:“price”}},“sales_deriv”:{“derivative”:{“buckets_path”:“sales”,“unit”:“day”}}}}}}
unit指定用于差值计算的x轴的单位,value原单位是每月,normalized_value单位为每天
分组脚本聚合
分组脚本聚合是父管道聚合,过程是执行一个脚本,使每个分组在父多组聚合的指定指标上执行计算。指标必须是数字型且脚本必须返回一个数字型的值
用bucket_script表示分组脚本聚合
{“bucket_script”:{“buckets_path”:{“my_var1”:“the_sum”,“my_var2”:“the_value_count”},“script”:“my_var1 / my_var2”}}
my_var1是用在脚本中的分组路径变量名;the_sum是用于变量的指标路径;script是聚合运行的脚本。脚本可以是内联、文件或索引
#利用分组聚合计算每个月T恤销售额占总量的百分比
{“aggs”:{“sales_per_month”:{“date_histogram”:{“field”:“date”,“interval”:“month”},“aggs”:{“total_sales”:{“sum”:{“field”:“price”}},“t-shirts”:{“filter”:“term”:{“type”:“t-shirt”}},“aggs”:{“sales”:{“sum”:{“field”:“price”}}}},“t-shirt-percentage”:{“bucket_script”:{“buckets_path”:{“tShirtSales”:“t-shirts>sales”,“totalSales”:“total_sales”},“script”:“tShirtSales / totalSales * 100”}}}}}}
串行差分聚合
串行差分聚合是一个机制,用时间序列上的值减去不同时间区间或时间周期的值。如,数据点f(x)=f(xt)-f(xt-n),其中n为经过的时间
时间段为1相当于没有时间规范的派生:只是把一个点换到下一个点。单时间周期可以用来移除常量,线性趋势,单周期也可以用来将数据转换为固定序列
用serial_dif表示串行差分聚合
{“serial_diff”:{“buckets_path”:“the_sum”,“lag”:“7”}}
参数说明:
buckets_path,指标路径
lag,当前分组覆盖历史分组,必须是非零正整数,可选,默认1
gap_policy,缺口策略,可选,默认insert_zero
format,聚合输出值格式,可选,默认null
串行差分聚合必须嵌入到直方图或日期直方图聚合中使用
{“aggs”:{“my_date_histo”:{“date_histogram”:{“field”:“timestamp”,“interval”:“day”},“aggs”:{“the_sum”:{“sum”:{“field”:“lemmings”}},“thirtieth_difference”:{“serial_diff”:{“buckets_path”:“the_sum”,“lag”:30}}}}}}
分组选择器聚合
分组选择器聚合是在聚合的结果执行一个脚本来决定当前分组是否应该保留。指定的指标必须是数字型且脚本必须返回一个布尔值。如果脚本语言是表达式,一个数字型的返回值也是全法的,在这种情况下,0.0视作假,其他值被视作真
用bucket_selector表示分组选择器聚合
{“bucket_selector”:{“buckets_path”:{“my_var1”:“the_sum”,“my_var2”:“the_value_count”},“script”:“my_var1 > my_var2”}}
my_var1是用在脚本中的分组路径变量名,the_sum是用于变量的指标路径;script是聚合运行的脚本,可以是内联、文件或索引
#仅保留每月销售总额小于等于50的分组
{“aggs”:{“sales_per_month”:{“date_histogram”:{“field”:“date”,“interval”:“month”},“aggs”:{“total_sales”:{“sum”:{“field”:“price”}},“sales_bucket_filter”:{“bucket_selector”:{“buckets_path”:{“totalSales”:“total_sales”},“script”:“totalSales <= 50”}}}}}}
第六章 集群管理
集群管理
集群管理相关内容包括:集群节点监控、集群分片迁移、集群节点配置、节点发现、集群平衡位置
6.1集群节点监控
集群监控包括集群的健康值、有关服务器的信息、节点信息、索引和分片信息等。监控API主要分为三类:
与集群相关的,以_cluster开头;
与节点相关的,以_nodes开头;
与任务相关的,以_tasks开头。
集群健康值
集群健康检查API _cluster/health
GET /_cluster/health?pretty=true
#后面加上索引名称,可以得到索引的健康检查情况
GET /_cluster/health/secisland?pretty=true
返回信息中,重点是status字段:
green,所有主、副分片都处于活动状态
yellow,所有主分片都处于活动状态,不是所有副本分片都处于活动状态
red,不是所有主分片都处于活动状态
集群状态
查询整个集群的综合状态信息 _cluster/state
GET /_cluster/state
返回信息非常多,主要有:集群信息、节点信息、索引结构信息、分片信息、路由信息(精细到每一个分片)等
GET /_cluster/state/blocks
GET /_cluster/state/metadata,routing_table/foo,bar
GET /_cluster/state/_all/foo,bar
集群统计
_cluster/stats 从一个集群的角度统计集群状态,返回两个最基本的信息,一是索引信息,如分片数量、存储大小、内存使用等,另一个是集群节点信息,如节点数量、角色、操作系统信息、JVM版本、内存使用率、CPU和插件的安装信息
GET /_cluster/stats
集群任务管理
GET /_tasks
GET /_tasks?nodes=nodeID1,nodeID2
GET /_tasks?nodes=nodeID1,nodeID2&actions=cluster:*
GET /_tasks/taskId1
GET /_tasks?parent_task_id=parentTaskId1
任务接口还可以用来等待任务的完成
#等待10秒或ID为otultx4-iqmouuveiohtt8a:12345的任务等待10秒
GET /_tasks/otultx4-iqmouuveiohtt8a:12345?wait_for_completion=true&timeout=10s
需要长时间等待的任务可以取消,取消操作可以取消一个或多个任务
POST /_tasks/taskId1/_cancel
POST /_tasks/_cancel?node_id=nodeId1,nodeId2&actions=reindex
待定集群任务
待定集群任务返回一个尚未执行的集群水平变化的列表,如创建索引、更新映射、分配分片或失败分片
GET /_cluster/pending_tasks
通常返回空,因为系统正常情况下处理很快
节点信息
集群节点信息接口用于搜索一个或多个集群节点的信息
GET /_nodes
GET /_nodes/os #仅查看os信息
GET /_nodes/hot_threads #查询活跃线程
GET /_nodes/{nodeIds}/hot_threads
返回信息包含:节点网络配置、配置文件路径、操作系统、JVM信息等等
settings/os/process/jvm/thread_pool/transport/http/plugins
节点统计
对一个、多个或全部集群节点进行统计
GET /_nodes/stats
GET /_nodes/node-1/stats
GET /_nodes/node-1/stats/os,fs
返回信息:
indices,索引相关的统计,包括size、document count 、indexing and deletion times、search times、field cache size、merges and flushes
fs,文件系统信息,包括路径、磁盘空间、读/写数据等
http,http连接信息
jvm,jvm虚拟机统计,包括内存池数据、垃圾回收、缓冲池、加载/卸载类等
os,操作系统统计,平均负载、内存、交换分区等
process,进程统计,包括内存消耗、处理器使用、打开的文件描述符等
thread_pool,线程池统计,当前大小、队列和拒绝的任务等
thansport,网络数据统计,集群通信中发送和接收字节统计
breaker,数据处理统计
script,脚本相关信息
6.2集群分片迁移
es中可以通过集群路由_cluster/reroute对集群中的分片进行操作,如可以把一个分片从一个节点迁移到另一个节点,将未分配的分片分配到一个特定节点上等。这个过程通常是自动运行的,如果想手动操作,必须将cluster.routing.allocation.disable_allocation参数设置为true,以禁止es自动索引分片分配。
POST /_cluster/reroute
{“commands”:[{“move”:{“index”:“test”,“shard”:0,“from_node”:“node1”,“to_node”:“node2”}},{“allocate”:{“index”:“test”,“shard”:1,“node”:“node3”}}]}
共有三种操作:
移动move,把分片从一节点移动到另一个节点,可以指定索引名和分片号
取消cancel,取消分配一个分片,可以指定索引名和分片号。node参数可以指定在哪个节点取消正在分配的分片,allow_primary参数支持取消主分片
分配allocate,分配一个未分配的分片到指定的节点,可以指定索引名和分片号。node参数指定分配到哪个节点;all_primary可以强制分配主分片,不过这可能导致数据丢失,因为allow_primary将使一个新的空主分片被分配,如果有一份原始的分片副本(含数据)的节点重新加入集群,分片副本数据将被删除:旧的分片副本将会被新的活动分片副本替换集群配置更新:系统允许对集群的配置进行更新,配置更新有两种状态,一是持久的,二是临时的
PUT /_cluster/settings
{“persistent”:{“discovery.zen.minimum_master_nodes”:2}}
#持久更新配置,将参数persistent换成transient就是临时更新
6.3集群节点配置
相同集群名的多个节点连接组成集群。默认每个节点都可以处理http请求和集群节点的数据传输。集群中所有节点都知道集群中其他的所有节点,可以将客户端的请求转发到适当的节点上
节点的类型
主节点master,当node.master设置为true(默认)时,就有资格被选作主节点,控制整个集群
数据节点data,当node.data设置为true(默认)时,该节点保存数据和执行数据相关的操作,如增删改查、搜索和聚合
默认,节点同时是主节点和数据节点,随着集群的发展,分离主节点和数据节点就变得有意义了
客户端节点,当节点的node.master和node.data都设置为false时,既不保持数据也不能成为主节点,该节点可以作为客户端节点,响应用户的请求,把相关操作转发到其他节点
部落节点,当一个节点配置tribe.时,它是一个特殊的客户端,可以连接多个集群,在所有连接的集群上执行搜索和其他操作
客户端节点也叫协调节点,需要有足够的内存和CPU以处理各个节点的返回结果
主节点
主节点主要负责和集群相关的内容,如创建或删除索引,跟踪哪些节点是集群的一部分,并决定哪些分片分配给相关的节点。默认任何一个节点都可以成为主节点,而索引数据和搜索查询等操作会占用大量的CPU、内存、IO资源,为确保集群的稳定,分离主节点和数据节点是较好的选择
主节点也可以作为协调节点,但最好不用主节点
创建一个独立的主节点的配置:
node.master:true
node.data.false
为防止数据丢失,配置discovery.zen.minimum_master_nodes至关重要(默认为1),每个主节点应该知道形成一个集群的最小数量的主资格节点的数量
设置这个值的原则是:(master_eligible_nodes/2)+1
该参数也可以动态设置:PUT /_cluster/settings {“transient”:{“discovery.zen.minimum_master_nodes”:2}} #persistent永久;transient临时
数据节点
存储索引数据的节点,主要对文档进行增删改查、聚合等。数据节点对CPU、内存、IO要求较高。应当监控数据节点的状态,当资源不足时,增加新节点数量
数据节点配置
node.master:false
node.data:true
数据节点路径设置
每一个主节点和数据节点都需要知道分片、索引、元数据的物理存储位置,path.data默认为$ES_HOME/data,可以通过配置文件设置
path.data: /var/elasticsearch/data
该设置也可以在命令行上执行
elasticsearch --path.data /var/elasticsearch/data
这个目录最好单独配置,当删除es主目录时,不会影响到数据
数据目录可以被多个节点共享,甚至可以属于不同的集群,为防止多个节点共享相同的数据路径,可以在配置文件中添加node.max_local_storage_nodes:1
注:在相同的数据目录不要运行不同类型的节点(master/data/client),这会导致意外的数据丢失
客户端节点
当主节点和数据节点都设置为false时,该节点只能处理路由请求,处理搜索、分发索引操作等,从本质上说客户端节点表现为智能负载平衡器
添加太多的客户端节点对集群是一种负担,因为主节点必须等待每一个节点集群状态的更新确认
配置:
node.master:false
node.data:false
部落节点
部落节点可以跨越多个集群,可以接收不同集群的状态,然后合并成一个全局集群的状态,它可以读写所有节点上的数据
配置参数:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 配置方法:
tribe:
t1:
cluster.name: cluster_one
t2:
cluster.name: cluster_two
部落节点可以通过block设置所有的写操作和所有的元数据操作
tribe:
blocks:
write: true
metadata: true
部落节点可以在选中的索引块中单独配置上面的操作
tribe:
blocks:
write.indices: hk,ldn
metadata.indices: hk*,ldn*
t1、t2是任意名字,代表连接到的集群。默认部落节点通过单播发现连接到每个集群。用于连接的其他配置可以配置在tribe{name}后
如果两个集群名称相同,那么部落节点只会连接其中一个。由于没有主节点,主节点级别的读操作:集群统计、集群健康度,会在本地标志设置为true的节点自动执行;主节点级别的写操作将被拒绝,如创建索引,这些操作应该在单个集群节点上执行
6.4节点发现
zen发现机制是默认的发现模块,提供单播发现方。
发现模块分为两个模块:
ping模块,通过ping模块可以寻找其他节点
单播模块,使用提供的主机列表作为路由列表,以discovery.zen.ping.unicast为前缀
主机列表设置:discovery.zen.ping.unicast.hosts,它是一个数组,多个主机以逗号分隔,格式为host:port,或者host[port1-port2],ip6主机必须在方括号内,如192.168.1.1,[::1]
单播发现依赖传输模块,port默认为9300
主节点选举
集群中,系统自动通过ping进行选举主节点或加入主节点,这是自动的
discovery.zen.ping_timeout,默认为3秒,允许对选举时间进行调整,以应对处理缓慢和拥挤的网络。
discovery.zen.join_timeout,默认为ping_timeout时间的20倍。当一个节点请求加入主节点,它会发送请求信息到主节点,此为请求的超时时间
当主节点发生问题时,现有节点会通过ping重新选举主节点。当节点node.master为false或者node.client为true时,它们将不会选举为主节点;node.master为true的节点一直有午觉权
discovery.zen.master_election.filter_client为true(默认)时,选举主节点时会排除node.client为true或node.data和node.master同时为false的节点
discovery.zen.master_election.filter_data为true时(默认false),选举主节点时大排除node.data为true,node.master为false的节点
discovery.zen.minimum_master_nodes,设置要加入一个新当选的主节点的最小节点数目,或者接收它作为主节点的最小节点数,若不满足,主节点会下台,重新选举
故障检测
有两种故障检测:一是由主节点到所有其他节点的验证,以证明它们还活着;二是每个节点ping主节点验证,以证明主节点还活着,当检测到主节点死掉后,会启动选举过程
控制故障检测使用discovery.zen.fd前缀的设置:
ping_interval,ping检查频率,默认为1秒
ping_timeout,ping超时,默认为30秒
ping_retries,重试次数,默认为3次
主节点是集群中可以改变集群状态(配置)的唯一节点,主节点发布更新,然后等待所有节点的确认应答,discovery.zen.publish_timeout为处理下一个更新队列前的超时时间,默认为30秒
一个健康的集群必须有一个主节点,且有多个满足主节点选举条件的节点,该数字由discovery.zen.minimum_master_nodes设置
discovery.zen.no_master_block用于设置没有有效的主节点时应当拒绝的操作,两两个选择:
all,该节点上的所有行为被拒绝,包括读写,同时拒绝集群状态的读写操作,如得到索引设置
write,基于最后一次集群配置,写操作被拒绝,允许读操作。这会导致部分读取的数据是过期的,因为该节点已从集群中分离,这是默认设置
discovery.zen.no_master_block不适用于基于节点状态的API,如cluster stats/node info/node stats
6.5集群平衡配置
主节点的主要作用是决定哪些分片分配给哪个结点,并在节点间移动分片以平衡整个集群
可以控制分片分配过程的设置:
分片分配设置,对集群进行分配和再平衡操作
基于磁盘的配置,根据可用磁盘空间大小来进行分配设置
分片智能分配,可以控制分片在不同机架或可用性区域中的配置
分片配置过滤,允许某些节点或节点组排除在分配的列表中,常用于需要停止的节点中
所有这些设置都是动态设置,可以通过集群接口进行实时更新
分片分配设置
分片分配过程是分片到节点的一个处理过程,可能发生在初始恢复过程中,副本分配中,再平衡过程中,或当节点被添加或删除时
1、分片分配设置
控制分片的分配和回收
cluster.routing.allocation.enable:禁用或者启用分片的类型,参数:
all,允许所有分片被重新分配
primaries,只允许主分片被重新分配
new_primaries,只允许新的主分片被重新分配
none,不对任何分片重新分配
cluster.routing.allocation.node_concurrent_recoveries:允许在一个节点上同时并发多少个分片分配,默认为2
cluster.routing.allocation.node_initial_primaries_recoveries,当副本分片加入集群时,在一个节点上并行发生分片分配的数量,默认为4
cluster.routing.allocation.same_shard.host:在一个主机上当有多个相同集群名称的分片分配时,是否进行检查,检查主机名和主机ip,默认为false,此设置仅适用于在同一台机器上启动多个节点时配置
indices.recovery.concurrent_streams:从一个节点恢复时,同时打开的网络流量数,默认为3
indices.recovery.concurrent_small_file_streams:从同伴分片恢复时打开每个节点的小文件(小于5M)流的数目,默认2
2、分片平衡设置
控制整个集群的碎片再平衡
cluster.routing.rebalance.enable:启用或禁用特定种类的分片重新平衡,可选参数有:
all,允许所有分片进行分片平衡,默认
primaries,只允许主分片进行平衡
replicas,只允许副本分片进行平衡
none,不允许任何分片进行平衡
cluster.routing.allocation.allow_rebalance:当分片再平衡时允许的操作,可选参数有:
always,总是允许再平衡
indices_primaries_active,只有主节点索引允许再平衡
indices_all_active,所有分片允许再平衡,默认
cluster.routing.allocation.cluster_concurrent_rebalance:再平衡时允许多少个并发的分片同时操作,默认为2
3、启发式分片平衡
确认在何处设置每个碎片的数据
cluster.routing.allocation.balance.shard:在节点上分配每个分片的权重,默认0.45
cluster.routing.allocation.balance.index:在特定节点上,每个索引分配的分片的数量,默认0.55
cluster.routing.allocation.balance.threshold:操作的最小最优化的值,默认1
基于磁盘的配置
es可以根据磁盘大小来决定是否重新进行分片的分配
cluster.routing.allocation.disk.threshold_enabled:是否启用磁盘分配决策,默认为true
cluster.routing.allocation.disk.watermark.low:允许分配时的磁盘空间最小值,可以是比例或者绝对值,如85%或者1G。当磁盘占用超过设定值后,系统将不会对节点进行分配操作
cluster.routing.allocation.disk.watermark.hith:允许保存分片节点磁盘空间的最大值,当超过此值后,系统会把分片迁移到别的节点,默认为90%。可设置比例或实际大小,如500mb
cluster.info.update.interval:检查集群中每个节点的磁盘使用情况的时间间隔,默认为30秒
cluster.routing.allocation.disk.include_relocations:当计算节点磁盘使用时需要考虑当前被分片的情况,默认true
#PUT /_cluster/settings {transient":{“cluster.routing.allocation.disk.watermark.low”:“80%”,“cluster.routing.allocation.disk.watermark.hith”:“5gb”,“cluster.info.update_interval”:“1m”}}
#每分钟检查一次磁盘,当磁盘已用空间小于80%时,参与分片分配;当可用空间不足5GB时,将节点分片迁移到别的节点
分片智能分配
解决多个节点在同一虚拟机、同一机架、同一网络区域时,因物理原因多个节点同时出故障的问题。
区域分片分配可以在启用时加上–node.rack_id接指定名称或配置到配置文件中:
elasticsearch --node.rack_id rack_one
cluster.routing.allocation.awareness.attributes:rack_id
也可以通过API接口设置
#假如有两个节点node.rack_id为rack_one,创建一个索引包含5个主分片和一个副本,那么主分片和副本分片会分配到这两个节点上;当我们新添加两个节点,node.rack_id为rack_two后,系统会自动分配主分片到新的节点上,确保没有两个相同的分片在同一区域中;当搜索时,系统会自动处理,只在一个区域中搜索
强制分配属性,解决不允许相同分片副本分配到同一区域的问题。如我们有两个区域,但每个区域的大小只够分配一半的分片
cluster.routing.allocation.awareness.force.zone.values:zone1,zone2
cluster.routing.allocation.awareness.attributes:zone
分片配置过滤
对索引的分片分配进行控制,允许或禁止分配到指定节点
可在移除节点前把节点上的分片移动到其他节点中
#停止10.0.0.1上的所有节点
#PUT http://127.0.0.1:9200/_cluster/settings {“transient”:{“cluster.routing.allocation.exclude._ip”:“10.0.0.1”}}
#这样,10.0.0.1节点上的分片会被迁移到其他节点
cluster.routing.allocation.include.{attribute}:将索引分配给一个节点,{attribute}至少有一个逗号分隔的值
cluster.routing.allocation.require.{attribute}:将索引分配给一个节点,{attribute}至少有一个逗号分隔的值
cluster.routing.allocation.exclude.{attribute}:将索引分配给一个节点,{attribute}至少有一个逗号分隔的值
attributes可能的值:
_name,通过节点名称匹配节点
_ip,通过ip匹配节点
_host,通过机器名称匹配节点
所有的属性值可以用通配符
#PUT /_cluster/settings {“transient”:{“cluster.routing.allocation.include._ip”:“192.168.2.*”}}
其他集群配置
cluster.blocks.read_only:使整个集群为只读
日志记录:设置日志记录的级别
#增加indices.recovery模块,其日志级别为DEBUG
PUT /_cluster/settings {“transient”:{“logger.indices.recovery”:“DEBUG”}}
第七章 索引分词器
es分词器,分词原理及过程、添加新的分词器、插件安装等
7.1分词器概念
分词器analyzer,词元token
分词器analyzer由一个分解器tokenizer、零或多个词元过滤器token filters组成;分解器处理前可以有预处理,为字符过滤器character filter;词元过滤器可以完成大小写转换、增加同义词等;处理后的结果称为索引词term
索引分析模块analysis包括分词器analyzer、分解器tokenizer、词元过滤器filters
分词器可以有别名
分词器测试
POST /_analyze
{“tokenizer”:“standard”,“filters”:[“lowercase”,“stop”],“text”:“SecIsland is a data company”}
analyzer、tokenizer、filters是三个关键字,analyzer在内容上包括tokenizer和filters,所以可以只输入analyzer或者tokenizer和filters自定义分词器
自定义分词器接受分解器tokenzier的逻辑/注册名,以及词元过滤器filter的逻辑名/注册名,自定义分词器不能以_开头,其设置为:
tokenizer,分解器的逻辑/注册名
filter,词元过滤器的逻辑/注册名
char_filter,字符过滤器的逻辑/注册名
position_increment_gap,每个使用本分词器字段的字段值之间可增加的位置,默认为100
7.2中文分词器
smartcn分词器
安装分词器
https://download.elastic.co/elasticsearch/release/org/elasticsearch/plugin/analysis-smartcn/2.4.5/analysis-smartcn-2.4.5.zip
cd elasticsearch-2.4.5/bin && ./plugin install analysis-smartcn
systemctl restart elasticsearch
卸载: ./plugin remove analysis-smartcn
测试:POST /_analyze {“analyzer”:“smartcn”,“text”:“联想是全球最大的笔记本厂商”}
IKAnanlyzer分词器
因为我现在使用的es是2.4.5,所以对应的IK版本为1.10.6
项目地址:https://github.com/medcl/elasticsearch-analysis-ik
https://github.com/medcl/elasticsearch-analysis-ik/archive/v1.10.6.zip
#编译代码
yum install maven
unzip v1.10.6.zip
cd elasticsearch-analysis-ik-1.10.6
#1.10.6对应的es版本是2.4.6,高于2.4.5,所以,需要编辑pom.xml文件,修改<elasticsearch.version>行,否则es会报错无法启动
mvn package
#将编译好的zip包elasticsearch-analysis-ik-1.10.6/target/releases/elasticsearch-analysis-ik-1.10.6.zip
#mkdir analysis-ik
cd elasticsearch-2.4.5/plugins/analysis-ik
unzip elasticsearch-analysis-ik-1.10.6.zip
systemctl restart elasticsearch
#测试
POST /_analyze {“analyzer”:“ik_max_word”,“text”:“联想是全球最大的笔记本厂商”}
POST /_analyze {“analyzer”:“ik_smart”,“text”:“联想是全球最大的笔记本厂商”}
POST /_analyze {“analyzer”:“ik”,“text”:“联想是全球最大的笔记本厂商”}
7.3插件
插件可以添加自定义映射类型、自定义分词器、本地脚本、自定义发现等
插件的类型:
Java插件,插件只包含jar文件,必须安装到集群中的每个节点上,安装后必须重启
站点插件,包含静态web内容,只需在一个节点上安装,不需要重启,通过URL访问,http://127.0.0.1:9200/_plugin/[pluginname]
混合插件,既包含jar文件又包含站点
插件管理
插件通过脚本进行管理,可以安装、查询、删除
./plugin [list/install/remove]
插件安装
#安装官方插件
bin/plugin install analysis-icu
#安装github插件
bin/plugin install [org]/[user|component]/[version]
bin/plugin install lmenezes/elasticsearch-kopf #脚本会先到官方下载,然后到maven.com去下载,然后去github去下载
#直接从maven中央库安装,版本号必须要写
#http://mvnrepository.com/artifact/org.elasticsearch.plugin
bin/plugin install org.elasticsearch.plugin/mapper-attachemts/3.0.0
#从本地安装
bin/plugin install file:///path/to/plugin.zip
有用的插件
#python脚本支持
./plugin install lang-python#使用SQL语法操作ES
#项目地址:https://github.com/NLPchina/elasticsearch-sql/
./plugin install https://github.com/NLPchina/elasticsearch-sql/releases/download/2.4.5.0/elasticsearch-sql-2.4.5.0.zip
systemctl restart elasticsearch
使用:
http://192.168.1.10:9200/_plugin/sql/
SELECT * FROM secisland
SELECT * FROM bank WHERE age >30 AND gender = ‘m’
select COUNT(*),SUM(age),MIN(age) as m, MAX(age),AVG(age) FROM bank GROUP BY gender ORDER BY SUM(age), m DESC
http://192.168.1.10:2200/_sql?sql=select * from secisland limit 10
注:2.4.5不支持delete命令
插件清单
插件分类:API插件、报警插件、分词插件、发现插件、管理和站点插件、映射器插件、脚本插件、安全插件、快照/恢复插件、传输插件
API插件
对es添加新的API特性或者功能,通常用于搜索或者映射
核心插件是delete-by-query,该插件通过查询删除文档,因为它是内部是一条一条删除的,不要用此方法删除大量文档,会导致耗时较长,比较好的方法是创建一个新的索引,把需要的文档copy过去
DELETE /secisland/secilog/_query?q=user:kimchy
DELETE /secisland/secilog/_query {“query”:{“term”:{“user”:“kimchy”}}}
其它插件:
carrot2 Plugin,基于carrot2或Lingo3G算法的聚合插件
SQL language Plugin,通过SQL语法来搜索ES
WebSocket Change Feed Plugin,通过WebSocket连接到ES节点接收数据报警插件
当ES索引等指标超出阈值时触发报警
Watcher,官方支持的收费报警插件分词插件
核心插件analysis-icu,集成lucene icu模块到ES,支持Unicode的ICU库
analysis-phonetic,语音分析插件
analysis-smartcn,中科院的中文分词插件,不支持扩展,不建议使用
analysis-stempel,支持lucene的stempel analysis模块
社区插件:
IK Analysis Plugin,比较好的中文插件
Mmseg Analysis Plugin,集成lucene mmseg4j-analyzer的插件,支持中文
Pinyin Analysis Plugin,集成Pinyin4j插件,支持汉字和拼音系统之间转换的java库,可自定义拼音输出格式发现插件
核心插件
AWS Cloud,亚马逊云
Azure Cloud,微软云
GCE Cloud,Google云
Multicast,组播插件发送多播消息
社区插件
eskka Discovery Plugin,支持Gossip协议的Akka Cluster集群节点
Kubernets Discovery Plugin,通过Kubernets API发现节点管理和站点插件
Marvel,官方支持的收费插件
Elasticsearch Head Plugin,社区免费
第八章 高级配置
es的配置一种是静态配置,另一种是动态配置;静态配置的参数只能在配置文件中事先写好,动态配置可以通过_cluster/settings进行配置
8.1网络相关配置
本地网关配置
本地网关是当所有集群重新启动时存储集群状态和分片数据的模块
下面的静态配置控制集群中每个节点在恢复任何本地存储的分片前,应该等待多长时间
gateway.expected_nodes,集群中预计节点(数据或主节点)的数量,本地分片恢复会在预计数量节点加入集群后开始执行,默认为0
gateway.expected_master_nodes,集群中主节点预计数量,本地分片恢复会在预计数量主节点加入集群后开始,默认0
gateway.expected_data_nodes,集群中数据节点预计数量,本地分片恢复会在预计数量数据节点加入集群后开始,默认0
gateway.recover_after_time,若没有达到预计节点数量,本地分片尝试恢复之前等待配置的时间,默认5m
HTTP配置
HTTP的配置不会动态更新
禁用HTTP,设置http.enabled为false以完全禁用。es节点间以及java客户端使用传输接口进行内部通信,而不是使用HTTP接口,可以在数据节点禁用HTTP
网络配置
es默认绑定本地网络地址
1、常用网络配置
其中,network.host特殊值有:
[networkInterface],网络接口地址,如_eth0_
local,回环地址,如127.0.0.1
site,本地站点地址,如192.168.1.10
global,系统中任何广域地址,如114.11.22.34
这些特殊值默认支持IPv4和IPv6,但也可以使用:ipv4和:ipv6进行限定,如_eth0:ipv4_,仅会绑定eth0接口的IPv4地址2、高级网络配置
通用网络配置中的network.host是同时设置绑定主机和发布主机的快捷方式。但在高级应用的情况中,如在代理服务器后面运行时,需要进行高级配置
network.bink_host,绑定网络接口来监听传入的请求,节点可以绑定多个接口,如两张网卡,或者本地站点地址和本地地址。默认为network.host的值
network.publish_host,发布主机是节点发布到集群中其他节点的单独接口,其他节点可以连接到本节点。节点可以绑定多个地址,但只能有一个发布地址,默认为network.bind_host中的最佳地址,然后根据可达性选择
这些设置接受和network.host同样的配置,接受IP地址、主机名和特殊值3、高级TCP配置
任何使用TCP协议的组件,如HTTP和传输模块共享这些设置
network.tcp.no_deplay,启用或禁用TCP无延迟设置,默认true
network.tcp.keep_alive,启用或禁用TCP保持连接,默认true
network.tcp.reuse_address,地址是否应该被重用,非windows上默认是true
network.tcp.end_buffer_size,TCP发送缓存的大小,默认没有显式设置
network.tcp.receive_buffer_size,TCP接收缓存大小,默认没有显式设置
传输配置
传输模块用于集群中节点间内部通信,传输机制本质上是异步的,线程不会被阻塞等待响应
1、TCP传输
TCP传输是传输模块TCP协议的一种实现
通过使用传输配置文件,es可以对不同接口绑定多个端口,如
transport.profiles.default.port:9300-9400
transport.profiles.default.bind_host:10.0.0.1
transport.profiles.client.port:9500-9600
transport.profiles.dmz.port:9700-9800
transport.profiles.dmz.bind_host:172.16.1.22、本地传输
这个方便的传输用于在JVM中执行集成测试,当使用NodeBuilder#local(true)时,会自动启用3、传输追踪
传输模块有专门的追踪日志,记录到达和发出的请求,通过将transport.tracer设置为TRACE,可以动态激活日志
PUT /_cluster/settings {“transient”:{“logger.transport.tracer”:“TRACE”}
使用包含和排除设置,可以控制需要追踪的行为
PUT /_cluster/settings {“transient”:{“transport.tracer.include”:“",“transport.tracer.exclude”:"internal:discovery/zen/fd”}}
8.2脚本配置
脚本默认是关闭的
可以通过配置来启用脚本引擎,在配置文件中添加如下内容
script.inline:true
script.indexed:true
可选的配置值:false,完全禁用;true,启用;sandbox,仅可用沙盒语言执行
默认配置值为:
script.inline:sandbox
script.indexed:sandbox
script.file:true可以在以下操作中执行脚本
aggs,聚合
search,搜索接口,过滤接口或建议接口,如filters、script_fields
update,升级接口
plugin,通用plugin类别下,脚本使用的任何插件
插件也要吧进行自定义操作,格式:KaTeX parse error: Expected group after '_' at position 13: {pluginName}_̲{operation},如在任何脚本引擎上禁用更新和映射
script.update:false
script.mapping:false
也支持明确的脚本语言设置,需要script.engine.前缀,优先权高于其他通用设置
script.engine.groovy.file.aggs:true
script.engine.groovy.file.mapping:true
script.engine.groovy.file.search:true
script.engine.groovy.file.update:true
script.engine.groovy.indexed.aggs:true
script.engine.groovy.indexed.mapping:true
script.engine.groovy.indexed.update:false
script.engine.groovy.indexed.plugin:false
script.engine.groovy.inline.aggs:true
script.engine.groovy.inline.mapping:false
script.engine.groovy.inline.search:false
script.engine.groovy.inline.update:true
script.engine.groovy.inline.plugin:false
系统默认使用Groovy作为脚本语言,可以通过配置script.default_lang进行修改
Groovy,非沙盒,内置
Expression,沙盒,内置
Mustache,沙盒,内置
JavaScript,非沙盒,elasticsearch-lang-javascript
Python,非沙盒,elasticsearch-lang-python
为增加安全性,es不允许在请求中指定非沙盒语言
脚本使用
使用脚本的三种方式
直接在请求体中使用脚本
把脚本存储在索引中,通过引用脚本id来使用
把脚本存储在本地磁盘中,默认位置elasticsearch/config/scripts,通过引用脚本名称进行使用PUT /secisland/secilog/1 {“eventCount”:1,“eventName”:“linux login event”}
方式一:
POST /secisland/secilog/1/_update {“script”:“ctx._source.eventCount+=count”,“params”:{“count”:4}
方式二:
先将脚本存储在es中
POST /_script/groovy/indexedCalculateCount {“script”:“ctx._source.eventCount+=count”}
POST /secisland/secilog/1/_upgrade {“script”:{“id”:“indexedCalculateCount”,“lang”:“groovy”,“params”:{“count”:8}}}
方式三:
先把脚本存储在文件中
文件名:indexedCalculateCount.groovy 内容:ctx._source.eventCount+=count
es对文件读取有个时间,不能立即生效,急的话可以重启es
POST /secisland/secilog/1/_update {“script”:{“file”:“indexedCalculateCount”,“lang”:“groovy”,“params”:{“count”:8}}}
脚本配置
1、索引脚本
es在名为_scripts的内部索引中存储脚本,并通过id进行引用,脚本请求格式为:/_scripts/{lang}/{id} 其中lang表示语言,id表示编号
保存脚本:
POST /_scripts/groovy/indexedCalculateScore {“scripts”:“log(_score*2)+my_modifier”}
使用脚本:
POST /_search
{“query”:{“function_score”:{“query”{“match”:{“body”:“foo”}},“functions”:[{“script_score”:{“script”:{“id”:“indexedCalculateScore”,“lang”:“groovy”,“params”:{“my_modifier”:8}}}}]}}}
查看脚本:
GET /_scripts/groovy/indexedCalculateScore
删除脚本:
DELETE /_scripts/groovy/indexedCalculateScore
2、启用动态脚本
在应用或者代理后执行es,可以从外界保护es,如果允许用户运行内联脚本或索引脚本,会继承运行es的用户权限。因此动态脚本默认仅支持沙盒语言
3、脚本自动重载
周期性扫描config/scripts目录的修改,更新脚本的载入,重载频率可以使用resource.reload.interval设置,默认为60秒
设置script.auto_reload_enabled为false可以完全禁用脚本重载
4、本地(java)脚本
有时,groovy和expressions是不够的,这种情况下,可以执行本地脚本,执行本地脚本的最好方式是编写且安装一个插件
5、lucene表达式脚本
lucene表达式提供一个机制将javascript表达式编译成字节码。表达式脚本也以用于script_score、script_fields、排序脚本和数字型聚合脚本
6、得分
聚合中所有可以使用的脚本,当前文档得分可以用_score获得
7、文档字段
大多数脚本围绕指定字段数据来使用,doc[‘field_name’]可以用来访问文档内指定字段的数据,但只能是简单字段,不能返回json对象,并且只有不分词或单索引词字段才有意义
8、保存的字段
执行脚本时,保存的字段也可以访问,通过使用_fileds[‘my_field_name’].value或_fields[‘my_field_name’].values
9、在脚本中访问文档得分
当使用脚本计算文档得分,可以在groovy脚本中使用_score变量访问得分
10、源字段
执行脚本时,可以访问源字段,每个文档都会加载源字段、分析并提供给脚本进行评估,如_source.obj1.obj2.field3
11、groovy内置方法
8.3快照和恢复配置
es中可以创建快照,他创建单个索引或整个集群到一个远程的存储库中。在执行快照操作前,需要在es中注册快照仓库。注册仓库的设置需要执行仓库类型请求
PUT /_snapshot/my_backup {“type”:“fs”,“settings”:{…repository specific settings…}}
注册后,可以通过查询来得到之前的注册信息。查询支持逗号分隔、支持通配符甚至_all查询多个注册信息
GET /_snapshot/my_buckup
#返回 {“my_backup”:{“type”:“fs”,“settings”:{“compress”:“true”,“location”:“/mount/backups/my_backup”}}}
共享文件系统存储"type":“fs"使用共享文件系统来存储快照。为注册共享文件系统存储库,必须将同一个共享文件系统安装到所有主节点和数据节点的相同位置上。这个位置必须在所有主节点、数据节点上设置path.repo参数。假设共享文件系统安装在/mount/backups/my_backup下,在elasticsearch.yml中设置如下:
path.repo:[”/mount/backups",“/mount/longterm_backups”]
path.repo支持Windows UNC路径:path.repo:[“\\MY_SERVER\Snapshots”]
只有当所有节点都重启后,可以使用下面的命令以名称为my_backup的共享文件系统库进行快照和恢复
PUT /_snapshot/my_backup {“type”:“fs”,“settings”:{“location”:“/mount/backups/my_backup”,“compress”:true}}
系统也支持相对路径,如
PUT /_snapshot/my_backup {“type”:“fs”,“settings”:{“location”:“my_backup”,“compress”:true}}
系统支持的参数如下:
location,快照位置,必须
compress,启用快照文件的压缩,压缩仅用于元数据文件,数据文件不进行压缩,默认为true
chunk_size,块大小,如1G,10m,5K,默认为null,不限制
max_restore_bytes_per_sec,每个节点恢复速度,默认为40MB/s
max_snapshot_bytes_per_sec,每个节点生成快照速度,默认为40MB/s
readonly,使存储库只读,默认为false
1、只读仓库
URL仓库(“type”:“url”)用于创建只读方式的数据仓库。URL参数支持HTTP、HTTPS、FTP、File、jar协议
在http、https、ftp协议中,支持白名单,在repositories.url.allowed_urls参数中配置
repositories.url.allowed_urls:[“http://www.example.org/root/","https://.mydomain.com/?#*”]
存储库可以通过插件的方式支持更多,如AWS的S3、Hadoop的HDFS等
注册一个存储库时,它立即在所有主节点和数据节点上验证,以确保在集群中所有节点上都可以使用。验证可以在注册或更新存储库时显示禁止
PUT /_snapshot/s3_repository?verify=false {“type”:“s3”,“settings”:{“bucket”:“my_s3_bucket”,“region”:“eu-west-1”}}
验证过程也可手动执行
POST /_snapshot/s3_repository/_verify
2、快照
一个存储库可以包含同一个集群的多份快照,快照在集群内名称是唯一的
#创建名称为snapshot_1的快照
PUT /_snapshot/my_backup/snapshot_1?wait_for_completion=true
默认会创建包含集群中所有打开和启动的索引的一个快照,也可以通过快照请求中的索引列来改变,如
PUT /_snapshot/my_backup/snapshot_1 {“indices”:“index_1,index_2”,“ignore_unavailable”:“true”,“include_global_state”:false}
索引快照是渐进的,即增量方式;快照过程是非阻塞的,不影响搜索和索引
#获取快照信息
GET /_snapshot/my_backup/snapshot_1
#查询正在运行的快照
GET /_snapshot/my_backup/_current
#从存储库中删除快照
DELETE /_snapshot/my_backup/snapshot_1
#删除存储库
DELETE /_snapshot/my_backup #删除存储库时,仅删除存储库的位置引用,快照本身并不被删除
3、恢复
POST /_snapshot/my_backup/snapshot_1/_restore
默认快照中的所有索引及集群状态将被恢复
include_global_state,指定具体的索引和集群状态被恢复
rename_pattern和rename_replacement,重命名索引,支持正则表达式,该表达式支持引用原始文本
include_aliases设置为false可以防止相关索引的别名被一起恢复
POST /snapshot/my_backup/snapshot_1/restore {“indices”:“index_1,index_2”,“ignore_unavailable”:“true”,“include_global_state”:“false”,“rename_pattern”:"index(.+)",“rename_replacement”:"restored_index$1"}
4、快照状态
#获得当前运行快照的详细状态信息列表
GET /_snapshot/_status
GET /_snapshot/my_backup/_status
GET /_snapshot/my_backup/snapshot_1/_status
#监视快照信息
GET /_snapshot/my_backup/snapshot_1
在恢复操作时,es集群通常会进入红色状态。因为还原开始恢复索引主分片,此时主分片会变得不可用,红色;恢复完成,es转换为标准复制,创建所需要的复本,黄色,最终,变为绿色
8.4线程池配置
节点包含多个线程池用来改善线程内存消耗,这些线程池有许多与之关联的队列,用来保留等待的请求,而不是丢弃
1、线程池类型
cached,无限的线程池,存在挂起的请求,就会产生一个线程。该线程池用于防止提交的请求被阻塞或者丢弃,线程池中无用线程会在持续期(默认5m)销毁。chched线程池保留为通用线程池。设置空闲时间
Python
1
2
3 threadpool:
generic:
keep_alive:2m
fixed,拥有固定大小的线程来操作队列中的请求直到请求没有线程提供服务。size控制线程数量,queue_size控制没有线程执行的请求队列的大小,默认为-1,即无限大。当请求到达且队列已经满了,请求会被中止
Python
1
2
3
4 threadpool:
index:
size:30
queue_size:1000
scaling,拥有动态数量的线程,线程数据与工作量成正比,且在1和size值之间变化,keep_alive参数决定一个线程的空闲时间
Python
1
2
3
4 threadpool:
warmer:
size:8
keep_alive:2m
2、处理器设置
处理器数量自动检测,线程池的设置会基于结果自动设置。有时,处理器数量会被错误检测,此时可以使用processors进行明确设置
8.5索引配置
索引模块包括分词、分片控制和分配、字段映射、索引相似性配置、慢查询记录、文件系统配置、控制事务和刷新模块
缓存配置
1、总内存控制
es中有很多控制器以防止内存溢出,每个控制器可以指定使用的最大值。此外,还有一个总的控制器,以确认系统使用的最大内存值。这些配置都可以动态更新
indices.breaker.tatal.limit,总的内存使用大小,默认为JVM堆内存的70%2、列数据内存控制
控制es在加载数据前估计数据量大小,若估计超过设定的阀值,会产生异常阻止该字段数据的加载
indices.breaker.fielddata.limit,列数据内存大小限制,默认为JVM堆内存的60%
indices.breaker.fielddata.overhead,所有列估计内存大小的乘积,默认是1.033、请求内存控制
防止每个请求的数据结构超过阀值
indices.breaker.request.limit,请求控制器大小,默认为JVM的40%
indices.breaker.request.overhead,所有请求的乘积,默认为14、数据缓存
现场数据缓存用于排序或聚合时,将所有字段值加载到内存中以便快速访问文档中的值
indices.fielddata.cache.size,数据缓存的最大值,可以是一个节点堆内存大小的比例,如30%,也可以是绝对值,如12GB,默认是无限。这个配置为静态配置,必须在节点每个数据节点启动前配置好,可以通过/_nodes/stats查看使用情况
5、节点查询缓存
缓存查询的结果。每个节点都有一个查询缓存。缓存使用最近最少使用算法,缓存满时,最少使用的数据优先删除。查询缓存只有使用过滤时才会起作用
indices.queries.cache.size,5%或者512MB,默认JVM的10%
6、索引缓冲区
用于存储新的索引文档,缓冲区满后,缓冲区的文件写入磁盘上的一个段。静态设置,必须在集群中每个数据节点上配置
indices.memory.index_buffer_size,节点索引缓冲区大小,为比例或绝对大小,默认为JVM的10%
indices.memory.min_index_buffer_size,最小索引缓冲区,默认48MB
indices.memory.max_index_buffer_size,最大索引缓冲区,默认无限制
indices.memory.min_shard_index_buffer_size,分配给每个分片索引缓冲区的内存最小值,默认4MB
7、分片请求缓存
请求缓存只缓存查询条件size=0的搜索,缓存的内容有hits.total、aggregations、suggestions,不缓存原始的hits。通过now查询的结果不缓存
缓存失效:只有分片数据实际上变化时刷新分片缓存才会失效。当缓存不够时,最少使用的数据将被删除
#默认缓存未启用,但在创建新的索引时可启用
PUT /secisland {“settings”:{“index.requests.cache.enable”:true}}
#动态设置
PUT /secisland/_settings {“index.requests.cache.enable”:true}
分片请求缓存是在节点级别进行管理的,默认为JVM的1%
indices.requests.cache.size:2%
8、索引恢复
indices.recovery.concurrent_streams,默认为3
indices.recovery.concurrent_small_file_streams,默认为2
indices.recovery.file_chunk_size,默认512KB
indices.recovery.translog_ops,默认1000
indices.recovery.translog_size,默认512KB
indices.recovery.compress,默认为true
indices.recovery.max_bytes_per_sec,默认为40MB
9、TTL区间
文档有个ttl值,可以设置当过期时是否需要删除
indices.ttl.interval,删除程序的运行时间,默认60s
indices.ttl.bulk_size,删除处理与批量请求的数量,默认10000
索引碎片分配
1、碎片分配过滤
控制哪个碎片被分配到哪个节点,启动时,可能随机将元数据属性分配给各个节点
#将test索引移动到bit或medium节点
PUT /test/_settings {“index.routing.allocation.include.size”:“big,medium”}
#从small节点移除test索引
PUT /test/_settings {“index.routing.allocation.exclude.size”:“small”}
#若指定多个规则,则所有条件必须满足
PUT /test/_settings {“index.routing.allocation.include.size”:“big”,“index.routing.allocation.include.rack”:“rack1”}
下面的设置是动态的,允许活动索引从一个节点移动到别一个节点
index.routing.allocation.include.{attribute},分配索引到一个节点,节点的{attribute}拥有至少一个逗号分隔的值
index.routing.allocation.require.{attribute},分配索引到一个节点,节点的{attribute}拥有所有逗号分隔的值
index.routing.allocation.exclude.{attribute},分配索引到一个节点,节点的{attribute}不拥有任何逗号分隔的值
{attribute}包含:
_name,通过节点名匹配节点
_host_ip,通过主机IP匹配节点,IP和主机名
_publish_ip,通过发布IP地址匹配节点
_ip,通过_host_ip或_publish_ip匹配
_host,通过主机名匹配节点
PUT /test/_settings {“index.routing.allocation.include._ip”:"192.168.2.*"2、延迟分配
延迟分配由于节点离开造成的未赋值碎片
副本分片的分配可以通过动态设置index.unassigned.node_left.delayed_timeout延迟,默认为1m
可以在一个活动索引(或所有索引)上更新设置
PUT /_all/_settings {“settings”:{“index.unassigned.node_left.delayed_timeout”:“5m”}
永久移除节点
如果一个节点不会返回集群且希望es立即分配缺失分片,可设置超时为0
PUT /_all/_settings {“settings”:{“index.unassigned.node_left.delayed_timeout”:“0”}}
在缺失分片已经开始恢复后重设延时3、每个节点的总碎片
每个节点对相同的索引限制碎片数量。
下面的动态设置可以强制限制每个节点允许单个索引分片的总数量
index.rouging.allocation.total_shards_per_node,分配到单个节点的最大分片数量(副本和主分片),默认没有限制
cluster.routing.allocation.tatal_shards_per_node,分配到单个节点的最大总分片数量(副本和主分片),默认没有限制
合并
合并小的分片为更大的分片来保持索引大小在范围内
index.merge.scheduler.max_thread_count,一次合并的最大线程数
相似模块
相似性(得分/排名模型)定义了匹配文档如何进行评分,相似性是针对字段的,通过映射可以对每个字段定义不同的相似性模块
1、配置相似性
“similarity”:{“my_similarity”:{“type”:“DFR”,“basic_model”:“g”,“after_effect”:“1”,“normalization”:“h2”,“nomalization.h2.c”:“3.0”}}
在映射中使用自定义相似性模块
{“book”:{“properties”:{“title”:{“type”:“string”,“similarity”:“my_similarity”}}}2、可用的相似性模块
默认相似性模块基于TF/IDF模式,拥有选项有:
discount_overlaps:决定重叠词元(词元的位置增量为0)是否要被忽略。默认true。
类型名:default
BM25相似性模块:基于TF/IDF,拥有内置的tf标准且对短字段(如名字)效率更高
参数:
k1,控制非线性索引词频率标准、饱和度
b,控制文档长度标准化到tf值的程度
discount_overlaps,决定重叠词元是否要被忽略,默认true
类型名:BM25
DFR相似性模块:实现随机性框架的分支
参数:
basic_model,可能的值有be、d、g、if、in、ine、p
after_effect,可能的值有no、b、l
nomalization,可能的值有no、h1、h2、h3、z
类型名:DFR
IB相似性模块:基于信息的模式,算法基于设想。对于书面文本这个方式会对比不同作者的写作风格
参数:
distribution,可能值ll、spl
lambda,可能值df、ttf
normalization,同DFR
类型名:IB
LM Dirichlet相似性模块
参数:
mu,默认2000
类型名:LMDirichlet
LM Jelined Mercer相似性模块
参数:
lambda,最佳值取决于采集和查询,标题查询约为0.1,长查询约为0.7
类型名:LMJelinekMercer
在elasticsearch.yml中要吧修改默认相似性模块
index.similarity.default.type:BM25
响应慢日志监控
1、搜索慢日志
该配置只针对当前分片节点有效
index.search.slowlog.threshold.query.warn:10s
index.search.slowlog.threshold.query.info:5s
index.search.slowlog.threshold.query.debug:2s
index.search.slowlog.threshold.query.trace:500ms
index.search.slowlog.threshold.fetch.warn:1s
index.search.slowlog.threshold.fetch.info:800ms
index.search.slowlog.threshold.fetch.debug:500ms
index.search.slowlog.threshold.fetch.trace:200ms
这些设置是动态的,且可以对每个索引进行设置
默认搜索慢日志没有启用(设置为-1),日志级别(warn、info、debug、trace),日志记录是在分片级别范围完成的
默认的配置文件是在logging.yml文件中:index_search_slow_log_file2、索引慢日志
日志文件以_index_indexing_slowlog.log结尾
日志和阈值在elasticsearch.yml中配置
index.indexing.slowlog.threshold.index.warn:10s
index.indexing.slowlog.threshold.index.info:5s
index.indexing.slowlog.threshold.index.debug:2s
index.indexing.slowlog.threshold.index.trace:500ms
index.indexing.slowlog.level:info
index.indexing.slowlog.source:1000
默认会记录_source中前1000个字符到慢日志中。设置为false或0会完全路过日志记录源,true则记录整个源
默认的配置文件在logging.yml文件中:index_indexing_slow_log_file
存储
存储模块可以控制索引数据如何在磁盘上存储和访问
windows64位:mmapfs;windows32位:simplefs;其他default,混合niofs和mmapfs
可以通过在elasticsearch.yml中配置
index.store.type:niofs
也可以在索引创建时静态设置
PUT /secisland {“settings”:{“index.store.type”:“niofs”}}
simplefs,使用随机存取文件,并发性较差,多线程会受到阻塞。当需要保留索引时,通常用niofs
niofs,使用NIO存储分片索引,多线程可以从同一文件同时读取数据,windows中不推荐这个类型,因为SUN Java的实现存在漏洞
mmapfs,通过映射文件到内存mmap存储分片索引,内存映射在进程中使用虚拟内存地址空间一部分,需要确保有充足虚拟地址空间
default_fs,NIO FS和MMapFS的混合,对每个类型的文件选择最佳的文件系统,如果索引词字典特别大,可以应用地址空间设置 sysctl -w vm.max_map_count=262144
事务日志
为防止数据丢失,每个分片都有事务日志translog或与之相关的日志,任何索引或删除操作在lucene索引内部执行后会被写入事务日志
flush操作是执行lucene提交并开始新的事务日志的过程
1、冲洗设置
下面的动态更新设置控制内存缓冲区数据保存到磁盘的频率
index.translog.flush_threshold_size,一旦事务日志达到这个大小,冲洗操作就会执行,默认512MB
index.translog.flush_threshold_ops,多少个操作之后执行冲洗,默认unlimited
index.translog.flush_threshold_period,无论事务日志大小,触发冲洗操作需要等待的时间,默认30m
index.translog.interval,多久检查一次不否需要执行冲洗操作,在间隔值和2倍间隔值之间随机,默认5s
2、事务日志设置
每个索引使用下面的动态更新设置控制事务日志
index.translog.sync_interval,事务日志多久被提交和同步到磁盘上,默认5s
index.translog.durability,请求完成后,事务日志是否同步和提交。request(默认),每次请求之后执行同步和提交。在硬件失败的情况下,所有收到的写入会事先提交到磁盘上;async经过一个同步间隔,都会后台执行同步和提交,在硬件失败的情况下,从最后一次自动提交之后收到的写入都会被丢弃
index.translog.fs.type,是否在内存中缓存事务日志。buffered(默认),事务日志先写入内存中64KB大小的缓存,且只有当缓存填满时才会写入磁盘,或者同步写请求或同步间隔触发;simple,事务日志立即写入文件系统,不用缓存,这些写入只会在同步和提交被触发时才会保存在磁盘上
第九章 告警监控和权限管理
https://pdf.us/2018/06/08/1267.html
告警、监控和权限管理
插件Wacher、Marvel、Shield可以对es进行告警监控、认证权限管理,但都是收费的
9.1告警
Watcher是进行告警和通知的插件,原理是在es中执行查询,满足条件后,产生告警
安装
1、安装Watcher插件
./plugin install license
#https://download.elastic.co/elasticsearch/release/org/elasticsearch/plugin/license/2.4.5/license-2.4.5.zip ->plugins/license
./plugin install watcher
#https://download.elastic.co/elasticsearch/release/org/elasticsearch/plugin/watcher/2.4.5/watcher-2.4.5.zip ->plugins/watcher
#安装Watcher需要额外的权限:getClassLoader、setContextClassLoader、setFactory
2、若es中设置了禁止自动创建索引,需要在配置文件中添加action.auto_create_index:.watches,.triggered_watches,.watcher-history*
3、重启es
systemctl restart elasticsearch
4、验证安装
GET /_watcher/stats?pretty
结构
1、Trigger
告警触发器,定义开始执行的时间点。创建一个触发器时,将这个触发器注册到一个合适的触发器引擎中。所有触发器都是基于时间的
触发器使用系统时钟来确定当前时间,所以需要同步所有节点的时钟。触发器的类型有:hourly、daily、weekly、monthly、yearly、cron、interval
1)hourly
每小时执行一次,可以设置具体的分钟,默认为0分钟
#在每小时的30分执行
{…“trigger”:{“schedule”:{“hourly”:{“minute”:30}}}…}
#在小时时刻中设置多个分钟
{…“trigger”:{“schedule”:{“hourly”:{“minute”:[0,15,30,45]}}}…}
2)daily
每天某一特定时间执行,可以配置具体时间,默认0点
{…“trigger”:{“schedule”:{“daily”:{“at”:"17:00}}}…}
{…“trigger”:{“schedule”:{“daily”:{“at”:[“midnight”,“noon”,“17:00]}}}…}
#midnight、noon是保留字,表示00:00和12:00
3)weekly
可以指定一周的名称、缩写或数字(星期日是一周的第一天)
sunday,monday,tuesday,wednesday,friday,saturday,sunday
sun,mon,tue,wed,thu,fri,sat ->1,2,3,4,5,6,7
{…“trigger”:{“schedule”:{“weekly”:{“on”:“friday”,“at”:“17:00”}}}…}
可以设置多个时间点
{…“trigger”:{“schedule”:{“weekly”:[{“on”:“tuesday”,“at”:“noon”},{“on”:“friday”,“at”:“17:00”}]}}…}
{…“trigger”:{“schedule”:{“weekly”:{“on”:[“tuesday”,“friday”],“at”:[“noon”,“17:00”]}}}…}
4)monthly
{…“trigger”:{“schedule”:{“monthly”:{“on”:10,“at”:“noon}}}…}
可以设置多个时间点
{…“trigger”:{“schedule”:{“monthly”:[{“on”:10,“at”:“noon”},{“on”:20,“at”:“17:00”}]}}…}
{…“trigger”:{“schedule”:{“monthly”:{“on”:[10,20],“at”:[“midnight”,“noon”]}}}…}
5)yearly
可以指定月的名称、缩写或数字
january,february,march,april,may,june,july,august,september,october,november,december
jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec -> 1…12
{…“trigger”:{“schedule”:{“yearly”:{“in”:“january”,“on”,10,“at”:“noon”}}}…}
可以设置多个时间点
{…trigger”:{“schedule”:{“yearly”:[{“in”:“january”,“on”:10,“at”:“noon”},{“in”:“july”,“on”:20,“at”:“17:00”}]}}…}
{…trigger”:{“schedule”:{“yearly”:{“in”:[“jan”,“dec”],“on”:[10,20],“at”:[“midnight”,“noon”]}}}…}
6)cron
,任意值;
?,日期和周会有相互影响,所以不能用而要用?,代表任意值
-,范围
/,每,5/20表示,5分触发一次,然后每20分触发一次,即5,25,45
,,枚举
L,表示最后,5L表示最后一个星期四
W,工作日,周一至周五,系统在离指定日期最近的有效工作日触发,5W,若5日是周六,则周五触发;若5日是周日,则周一触发
LW可以连用,表示某月最后一个工作日,即最后一个星期五
#,用于确定每个月的第几个星期几,4#2表示某月第二个星期三
{…“trigger”:{“schedule”{“cron”:“0 0 12 * * ?”}}…} 每天中午12点执行
7)interval系统内置表达式
系统内置表达式可设置seconds、minutes、hours、days、weeks
Xs,每多少秒执行一次,30s,每30s执行一次
Xm,Xh,Xd,Xw
{…“trigger”:{“schedule”:{“interval”:“5m”}}…}
2、inputs
输入将静态数据加载到告警执行上下文中作为判断的内容,支持四种输入源:simple、search、http、chain
1)simple input简单输入
将静态内容加载到告警执行上下文中,可以定义字符串、数值、或一个对象作为输入源
#提醒电子邮件
{“trigger”:{“schedule”:{“daily”:{“at”:“noon”}}},“input”:{“simple”:{“name”:“John”}},“actions”:{“reminder_email”:{“email”:{“to”:“to@host.domain”,“subject”:“Reminder”,“body”:“Dear {{ctx.payload.name}},by the time you read this,i will be gone”}}}}
2)search input搜索输入
将搜索结果作为输入加载到告警执行上下文中作为判断内容。conditions、transforms、actions都可以通过结果属性访问搜索中的内容
ctx.payload.hits 表示搜索的所有内容
ctx.payload.hits.total 表示搜索的结果条数
ctx.payload.hits.hits.2 搜索结果的第三条数据
#搜索所有日志作为输入
“input”:{“search”:{“request”:{“indices”:[“logs”],“types”:[“event”],“body”:{“query”:{“match_all”:{}}}}}}
#通过模板搜索的日志作为输入
{“input”:{“search”:{“request”:{“indices”:[“logs”],“template”:{“id”:“my_template”,“params”:{“value”:23}}}}}}
3)HTTP input HTTP协议输入
通过HTTP请求es得到的返回结果作为输入加载到告警执行上下文中作为判断的内容
“input”:{“http”:{“request”:{“host”:“example.com”,“port”:9200,“path”:“/idx/_search”}}}
#通过DSL语言进行查询
“input”:{“http”:{“request”:{“host”:“host.domain”,“port”:9200,“path”:“/idx/_search”,“body”:“{“query”:{“category”:“event”}}}”}}}
#通过模板进行查询
“input”:{“http”:{“request”:{“host”:“host.domian”,“port”:9200,“path”:“/{{ctx.watch_id}}/_search”,“body”:“{“query”:{“range”:{”@timestamp":{“from”:“{{ctx.trigger.triggered_time}}||-5m”,“to”:“{{ctx.trigger.triggered_time}}”}}}}“}}}
#通过调用es API进行查询
“input”:{“http”:{“request”:{“host”:“host.domain”,“port”:“9200”,“path”:”/_cluster/stats",“params”:{“human”:“true”}}}}
4)chain input链式输入
一次把多个输入加载到告警执行上下文中作为判断的内容
基于来自多个源的数据执行操作时,链输入是有用的。可以使一个输入收集的数据是从另一个源加载数据
{“input”:{“chain”:{“inputs”:[{“first”:{“simple”:{“path”:“/_search”}}},{“second”:{“http”:{“request”:{“host”:“localhost”,“port”:9200,“path”:“{{ctx.payload.first.path}}”}}}}]}}}
3、condition
当一个告警被触发时,condition决定是否执行下一步的动作。支持四种类型:always、never、script、compare
1)always 始终执行
“condition”:{“always”:{}}
2)never 永远不执行
PUT _watcher/watch/my-watch {…“condition”:{“never”:{}}…}
3)script 用脚本作为判断的条件,默认groovy
“condition”:{“script”:“return true”}
可以使用文件脚本源
“condition”:{“script”:{“file”:“my_script”,“lang”:“javascript”,“params”:{“result”:true}}}
4)compare 将执行上下文模型中的值与给写的值进行比较
#查询结果条数大于等于5时满足条件
{…“condition”:{“compare”:{“ctx.payload.hits.total”:{“gte”:5}}…}
eq,not_eq,gt,gte,lt,lte
{…“condition”:{“compare”:{“ctx.payload.aggregations.status.buckets.error.doc_count”:{“not_eq”:“{{ctx.payload.aggregations.handled.buckets.true.doc_count}}”}}…}
4、transform
可选项,在输入到执行动作过程中的数据处理,包括全局转换和局部转换
转换支持搜索、脚本和链转换,分别用search、script、chain表示
search转换是搜索的转换,用返回的搜索结果替换告警上下文中的内容
{“transform”:{“search”:{“request”:{“indices”:[“logstash-"],“body”:{“size”:0,“query”:{“match”:{“priority”:“error”}}}}}}}
script转换是在集群上执行脚本的转换,用返回的脚本执行结果替换告警执行上下文中的内容
{…“transform”:{“script”:“return[time:ctx.trigger.scheduled_time]”}…}
chain转换可以一次把多个转换加载到转换中
“transform”:{“chain”:[{“search”:{“indices”:["logstash-”],“body”:{“size”:0,“query”:{“match”:{“priority”:“error”}}}}},{“script”:“return [error_count:ctx.payload.hits.total]”}]}
5、action
当满足告警条件时会发生的动作。可以是邮件、HipChat、Slack等
PUT http://127.0.0.1:9200/_watch/watch/log_event_watch
{“metadata”:{“color”:“red”},
“trigger”:{“schedule”:{“interval”:“5m”}},
“input”:{“search”:{“request”:{“indices”:“log-events”,“body”:{“size”:0,“query”:{“match”:{“status”:“error”}}}}}},
“condition”:{“script”:“return ctx.payload.hits.total > 5”},
“actions”:{“email_administrator”:{“throttle_period”:“15m”,“email”:{“to”:“sys.admin@host.domain”,“subject”:“Encountered {{ctx.payload.hits.tatal}} errors”,“body”:“Too many error in the system, see attached data”,“attachments”:{“attached_data”:{“data”:{“format”:“json”}}},“priority”:“high”}}}}
示例
#寻找错误事件的一个告警定义
PUT http://127.0.0.1:9200/_watcher/watch/log_event_watch
{“metadata”:{“color”:“red”}, #元数据,可将可选的静态元数据附加到告警上
“trigger”:{“schedule”:{“interval”:“5m”}}, #触发,每5分钟执行一次
“input”:{“search”:{“request”:{“indices”:“log-events”,“body”:{“size”:0,“query”:{“match”:{“status”:“error”}}}}}}, #输入,搜索错误事件,并将响应加载到告警内容中
“condition”:{“script”:“return ctx.payload.hits.tatal > 5”}, #条件,是否超过5个错误事件
“transform”:{“search”:{“request”:{“indices”:“log-events”,“body”:{“query”:{“match”:{“status”:error"}}}}}}, #转换,若满足告警条件,所有动作都访问这个转换
“actions”:{“my_webhook”:{“webhook”:{“method”:“POST”,“host”:“mylisteninghost”,“port”:9200,“path”:“/{{watch_id}}”,“body”:“Encountered {{ctx.payload.hits.total}} errors”}},
“email_administrator”:{“email”:{“to”:“sys.admin@host.domain”,“subject”:“Encounted {{ctx.payload.hits.total}} errors”,“body”:“Too many error in the system, see attached data”,“attachment”:{“attatched_data”:{“data”:{“format”:“json”}}},“priority”:“hith”}}}} #两个动作#检查集群健康状态的告警定义
PUT http://127.0.0.1:9200/_watcher/watch/cluster_health_watch
{“trigger”:{“schedule”:{“interval”:“10s”}},“input”:{“http”:{“request”:{“host”:“127.0.0.1”,“port”:9200,“path”:“/_cluster/health”}}},“condition”:{“compare”:{“ctx.payload.status”:{“eq”:“red”}}},“actions”:{“send_email”:{“email”:{“to”:“admin@domain”,“subject”:“Cluster Status Warning”,“body”:“Cluster status is RED”}}}}
告警输出配置
告警可以输出到email、webhook、logging、hipchat、slack、pagerduty
1、email
在elasticsearch.yml中配置邮件帐户并重启es
2、webhook
用于提交web数据,不需要单独配置,只需在actions中配置
“actions”:{“my_webhook”:{“transform”:{…},“throttle_period”:“5m”,“webhook”:{“method”:“POST”,“host”:“mylisteningserver”,“port”:“9200,“path”:”😕{{ctx.watch_id}}“,“body”:”{{ctx.watch_id}}:{{ctx.payload.hits.total}}"}}}3、logging
记录日志到es中,不需要单独配置,只需在actions中配置
“actions”:{“log”:{“transform”:{…},“logging”:{“text”:“executed at {{ctx.execution_time}}”}}}4、hipchat、slack、pagerduty
在国内很少用
告警管理
1、列出告警
搜索索引.watches列出所有告警的配置
GET http://127.0.0.1:9200/.watches/_search
{“fields”:[],“query”:{“match_all”:{}}}2、删除告警
DELETE http://127.0.0.1/_watcher/watch/cluster_health_watch
9.2监控
监控主要分为六个层面:集群层、节点层、索引层、分片层、事件层、Sense
安装
Marvel有两个组件,一个是代理,安装在es集群中;一个是Kibana插件
#安装Marvel插件
./plugin install license
./plugin install marvel-agent
#https://download.elastic.co/elasticsearch/release/org/elasticsearch/plugin/marvel-agent/2.4.5/marvel-agent-2.4.5.zip
#需要权限setFactory、setHostnameVerifier
systemctl restart elasticsearch#安装Kibana的Marvel插件
./kibana plugin --install elasticsearch/marvel/latest
#https://download.elastic.co/elasticsearch/marvel/marvel-latest.tar.gz
systemctl restart kibana
配置
1、监控参数配置
可以在每个节点的elasticsearch.yml中配置marvel参数
marvel.agent.cluster.state.timeout:收集集群状态的超时时间,默认10秒
marvel.agent.cluster.state.stats.timeout:收集集群统计的超时时间,默认10秒
marvel.agent.indices:控制哪些索引数据被收集,默认所有索引,test1,test2,testd* +test*,-test3
marvel.agent.index.stats.timeout:收集索引统计的超时,默认10秒
marvel.agent.indices.stats.timeout:收集总索引统计超时时间,默认10秒
marvel.agent.exporters:配置代理监测数据。默认,代理安装在本地的集群上,它监控数据,使用HTTP协议将数据发送到一个单独的监控集群上
marvel.agent.index.recovery.active_only:是否收集所有的恢复数据,默认false
marvel.agent.index.recovery.timeout:收集恢复数据的超时时间,默认10秒
marvel.agent.interval:收集数据样本的频率,默认10秒,-1表示禁用数据
marvel.history.duration:监控创建的索引被自动删除的保留时间,默认7天,-1表示禁用自动删除2、监控索引配置
存储从集群中收集的数据
默认模板 GET /_template/.marvel-es-1 数据模板/_template/.marvel-es-data-1
默认仅一个分片,没有副本。可以覆盖默认设置
PUT /_template/custom_marvel {“template”:“.marvel*”,“order”:1,“settings”:{“number_of_shards”:5,“number_of_replicas”:2}}3、kibana配置相关
kibana.yml中可以设置marvel监控参数,通常默认值就可以很好工作
marvel.max_bucket_size:桶数量,默认10000
marvel.min_interval_seconds:时间桶能表示的最小秒数,默认10秒
marvel.node_resolver:被认为是唯一节点的标志
marvel.report_stats:是否将集群统计数据发送到Elastic公司,默认为true4、tribe部落节点监控配置
若通过部落节点连接到一个集群,需要在部落节点以及集群中的节点上安装监控代理来监控集群。若集群上设置了权限,还需要在部落节点上安装和配置权限
9.3权限管理
Shield
#安装shield
./plugin install license
./plugin install shield
#https://download.elastic.co/elasticsearch/release/org/elasticsearch/plugin/shield/2.4.5/shield-2.4.5.zip
#需要权限setFactory
systemctl restart elasticsearch
#添加管理员帐号
bin/shield/esusers useradd es_admin -r admin #注意用户名是es_admin,执行后设置密码
配置文件位于config/shield
logging.yml
role_mapping.yml,LDAP映射
roles.yml,定义用户角色
users,保存用户名和密码
users_roles,保存用户角色
工作原理
Shield安装后,会拦截所有API请求,然后对请求进行认证和授权校验。插件提供SSL安全协议、审计日志记录等功能
1、用户认证
可以基于数据库、本地文件、LDAP、AD或KPI记录用户数据2、授权
资源,集群、索引、别名等
权限,对资源的操作
许可,对应安全资源的一个或多个权限,2种许可:集群、索引
角色,权限的集合
用户,3、节点认证和信道加密
可以使用SSL/TLS,启用时,节点相互交换验证证书,建立节点间的信任,验证未经身份验证的节点加入集群,通过验证后,内部通信是加密的4、IP过滤
可设置白名单或黑名单,可设置IP或网段5、审计
日志记录,包含登录、授权、拒绝访问等
用户认证
用户认证方式
Native,内置本地认证;File,内置基于文件的认证;LDAP,目录协议;AD,活动目录服务;PKI,X.509证书
支持多种认证方式,按顺序进行认证,在elasticsearch.yml中配置
匿名用户访问
认证过程分为两个阶段:令牌提取和用户认证。默认匿名请求被拒绝,可以通过配置启用,elasticsearch.yml
本地认证
默认内置,不配置也可以
可以通过Users API完成本地认证用户的管理
#新增用户ironman
POST /_shield/user/ironman {“password”:“admin888”,“roles”:[“admin”,“power_user”],“full_name”:“Tony John”,“email”:“tony@example.com”,“metadata”:{“intelligence”:7}}
##用户密码和角色为必填项,其他为可选
#查询本地用户
GET /_shield/user
#删除用户
DELETE /_shield/user/ironman
LDAP认证
需要配置LDAP域和指定LDAP角色的角色映射。与LDAP的通信必须使用SSL/TLS加密。
用户组所属的角色定义用户的权限
SSL/TLS加密配置方法:
1)生成证书
cd CONFIG_DIR/shield
keytool -importcert -keystore node01.jks -file cacert.pem -alias ldap_ca
2)配置elasticsearch.yml
shield.ssl.keystore.path: /home/es/config/shield/node01.jks
shield.ssl.keystore.password: myPass
shield.ssl.keystore.key_password: myKeyPass
3)配置LDAP协议的URL和端口,如url:ldaps://ldap.example.com:636
4)重启es
AD认证
需要配置AD域和指定的AD角色在角色映射文件中。和AD角色通信必须用SSL/TLS。
PKI认证
要求客户提供X.509证书
基于文件的授权
内置方式。通过esusers控制台命令增加和删除用户,分配用户角色,管理用户和密码
#增加用户
esusers useradd
#增加用户同时设置密码
esusers useradd -p
#增加用户同时设置角色
esusers useradd -r <role1,role2>
#查询用户
esusers list
#管理密码
esusers passwd -p
#分配角色,-a增加角色,-r删除角色
esusers roles -a <role1,role2> -r
#删除用户
esusers userdel
角色管理
Shield提供基于角色的访问控制,默认情况下,所有操作都受限。只有给用户分配角色后,用户才可以执行授权内的操作
1、增加角色
POST /_shield/role/my_admin_role {“cluster”:[“all”],“indices”:[{“names”:[“index1”,“index2”],“privileges”:[“all”],“fields”:[“title”,“body”],“query”:“{“match”:{“title”:“foo”}}”}],“run_as”:[“other_user”]}
2、查看角色
GET /_shield/role3、删除角色
DELETE /_shield/role/my_admin_role
综合示例(略)
第十章 ELK应用
10.1 Logstash
插件管理
#列出现有插件
./logstash-plugin list
./logstash-plugin list --verbose #可以显示插件版本号
./logstash-plugin list --group output
#增加插件
./logstash-plugin install logstash-output-kafka
#更新插件
./logstash-plugin update
./logstash-plugin update logstash-output-kafka
#移除插件
./logstash-plugin uninstall logstash-output-kafka
Elasticsearch 5.0的特性与改进
5.0.0版本时间2016.10.27 2.4->5.0
elasticsearch 6.3 启动要求用户不能为root,且虚拟内存、文件描述符、最大线程数有要求,需要这样操作:
sysctl -w vm.max_map_count=262144 #临时修改
vi /etc/security/limits.conf #生新需重新登录
dong hard nofile 65536
dong soft nofile 65536
dong hard nproc 4096
dong soft nproc 4096
ERROR: [3] bootstrap checks failed
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]
[2]: max number of threads [3886] for user [dong] is too low, increase to at least [4096]
[3]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
新特性
索引性能提升、新增内置脚本Painless、新增几种数据结构、增加接口、java REST客户端
索引性能:提高25%~80%效率
数据转换节点Ingest Nodes,不依赖于Logstash实现常用的过滤能力,如grok、split、convert、date等。可以在任何节点开启转换功能或建立单独的转换节点。默认开启转换能力,要关闭,需要在配置文件中添加:node.ingest:false
#定义管道,设置foo的值始终为bar
PUT /_ingest/pipeline/my-peline-id {“description”:“describe pipeline”,“processors”:[{“set”:{“field”:“foo”,“value”:“bar”}}]}
#使用管道
PUT /secisland/secilog/my-id?pipeline=my-peline-id {“foo”:“text”}
新的脚本引擎Painless,基于安全和性能,Painless使用白名单限制函数与字段的访问,只做数据的操作,更加轻量级,速度要快好几倍,支持Java静态类型,语法和Groove类似,支持Java和lambda表达式
新的数据结构,集成Lucene 6,对数字类型和地理类型增加新的点数据结构,K-Ds树,它改变了数字类型的索引和搜索,增加35%查询速度、71%索引速度、减少66%磁盘空间、减少85%内存使用。新增加的IP字段支持IPv4和IPv6。地理点查询性能增加一倍
友好性接口变化:
索引:
增加Shrink接口,可以收缩分片数。Rollover接口,对日志类数据按天分割,不需要用logstash-[YYYY-MM-DD]的索引模板方式
PUT /logs-000001
{“aliases”:{“logs_write”:{}}}
POST logs_write/_rollover
{“conditions”:{“max_age”:“7d”,“max_docs”:1000}}
先创建logs-000001索引,别名为logs_write,然后创建rollover规则,文档超过1000或保存天数超过7天,则会自动切换到logs-000002
新增Depreated logging,将标志为废弃的命令记录到日志中
新增Cluster allocation explain接口,查询分片不能分配的原因
弹性:
索引数据路径采用UUID,增加新的内存控制器,正常情况下内存不足的情况基本不会发生
索引映射的变化
String类型
Text/Keyword替换String
“test”:{“type”: “text”,“fields”: {“keyword”: {“type”: “keyword”,“ignore_above”: 256}}}
数字类型
数字采用全新数据结构BKD tree,数字类型将不参与索引评分,要评分可同时映射数字类型和keyword类型,如
PUT /secisland {“mappings”:{“my_type”:{“properties”:{“my_number”:{“type”:“long”,“fields”:{“keyword”:{“type”:“keyword”}}}}}}}
geo_point字段
该字段也使用BKE tree结构,从根本上进行多维空间数据支持,将不再支持geohash、geohash_prefix、geohash_precision、lat_lon
_timestamp和_ttl字段
元字段_timestamp和_ttl将不再支持,对_timestamp可以在文档中添加日期字段代替或者用ingest pipline,如
PUT /_ingest/pipeline/timestamp {“description”:“Adds a timpstamp field at the current time”,“processors”:[{“set”:{“field”:“timestamp”,“value”:“{{_ingest.timestamp}}”}}]}
PUT /newindex/type/1?pipeline=timestamp {“example”:“data”}
对于_ttl可以用time-based索引或者在一个时间戳字段范围查询_delete-by-query来替换
POST /index/type/_delete_by_query {“query”:{“range”:{“timestamp”:{“lt”:“2016-05-01”}}}}
索引属性
所有在用的字段类型,除了废弃的string,索引属性只有true/false两种,代替之前的not_analyzed/no
非索引字段的文档值
之前,设置字段属性index:no将禁用文档的值,现在文档值对数字和boolean类型的值总是有效,除非doc_values设置为false
字段映射限制
对索引字段进行限制,最大1000个字段,字段最大深度20层。_parent字段不再索引,为找到文档中引用的父id,可以使用新的parent_id来进行查询。_source映射不再支持格式选项
_all查询的精度
每个字段长度由4个字节压缩到1个字节,空间效率更高,索引时间计算不太准确
percolator类型
percolator字段类型解析json结构到本地并存储到索引中。percolator先存储搜索,然后用文档来进行查询是匹配搜索。
映射percolator字段类型,该类型适用于percolate查询
{“properties”:{“query”:{“type”:“percolator”}}}
下面的json代码段可以被索引为一个本地查询
{“query”:{“match”:{“field”:“value”}}}
一个索引中只能有一个percolator类型字段
1、percolate查询
将存储在索引中的查询进行字段匹配。
PUT /secisland
{“mappings”:{“doctype”:{“properties”:{“message”:{“type”:“text”}}},“queries”:{“properties”:{“query”:{“type”:“percolator”}}}}}
Elasticsearch 6.X中,一个index只能有一个type,推荐的type名是 _doc
PUT /secisland
{“mappings”:{“doctype”:{“properties”:{“message”:{“type”:“text”},“query”:{“type”:“percolator”}}}}}
#在percolator中添加一个查询
PUT /secisland/doctype/1?refresh
{“query”:{“match”:{“message”:“bonsai tree”}}}
#在登记的percolator的查询中匹配文档
POST /secisland/_search
{“query”: {“percolate”: {“field”: “query”,“document”: {“message”: “A new bonsai tree in the office”}}}}
参数说明:
field,定义percolator字段,必填
document_type,映射的稳定字段,必填;es6中一个索引仅支持一个类型,没有该字段
document,需要匹配的原始文档。也可以在存储在索引中的文档,在这种情况下,文档参数可以被替换为这些参数:index、type、id、routing、preference、version
#添加一条待查询数据
PUT secisland/doctype/2 {“message”:“A new bonsai tree in the office”}
#查询可以这样写
GET secisland/_search
{“query”:{“percolate”:{“field”:“query”,“index”:“secisland”,“type”:“doctype”,“id”:“2”}}}
2、percolate查询高亮显示
索引的变化
当运行索引映射的时候禁止关闭或删除索引操作
索引别名不再支持索引路由,同时也不支持搜索路由
接口相关的变化
创建索引的方式只能用PUT
配置相关的变化
node.client设置被移除,若设置节点将无法启动。可以通过分别设置node.master、node.data、node.ingest来设置节点的类型
gateway。format设置被取消,默认用format设置smile
index.analysis.analyzer.default_index不再支持,替代为index.analysis.analyzer.default
通过系统属性配置es进行了调整,通过命令行参数设置将取消、通过java环境变量设置将取消、通过ES_JAVA_OPTS环境变量设置将取消
打包接口的变化
java虚拟机选择参数配置被放在新的配置文件jvm.options中,这意味着通过环境变量设置的参数被取消了
/bin/bash文件被依赖
脚本的变化
默认脚本语言从Groovy到Painless,Painless更安全、更快。语法上的不同在参数上,所有Painless参数必须有一个前缀
script.default_lang被移除,因为系统不再支持默认其他脚本语言,若要使用,需要在请求参数中显式指出
内联脚本将不再被使用;script和script_file参数将不再有效,由基于脚本或者模板的文件file来代替;基于文件的脚本用法将不再有效;script_id参数将不再被使用,由id来代替;模板查询中的query参数将不再被使用,由inline参数代替;搜索模板中的顶层模板template字段被替换为一致的模板/脚本对象语法
HTTP协议的变化
HTTP协议请求压缩始终被支持
所有节点都会写入数据到磁盘,包括node.data:false和node.master:false时
elk + kafka + zookeeper生产实践
1.查看系统版本
2.确认基础环境
3.安装zookeeper
4.安装kafka
5.安装filebeat
6.安装Elasticsearch
7.安装kibana
8.安装Logstash
9.关联配置
10.最终验证
https://www.elastic.co/downloads