Elasticsearch
为了避免es升级导致数据(📁data
)与日志的丢失(📁log
),通常配置(config/elasticsearch.yml
)数据与日志的存放位置非es
程序存放位置
节点角色
- master:候选节点(具有投票权)
- data:数据节点
- data_content:数据内容节点
- data_hot:热节点
- data_warm:索引不再定期更新,但仍可查询
- data_code:冷节点,只读索引
- Ingest:预处理节点,作用类似于Logstash中的Filter
- ml:机器学习节点
- remote_cluster_client:候选客户端节点
- transform:转换节点
- voting_only:仅投票节点(master主节点宕机后投票选举新的master)
- 协调节点(每个节点默认都是)
分片
- 一个索引包含一个或多个分片,在7.0之前默认五个主分片,每个主分片一个副本;在7.0之后默认一个主分片。副本可以 在索引创建之后修改数量,但是主分片的数量一旦确定不可修改,只能创建索引
- 每个分片都是一个Lucene实例,有完整的创建索引和处理请求的能力
- ES会自动再nodes上做分片均衡
- 一个doc不可能同时存在于多个主分片中,但是当每个主分片的副本数量不为一时,可以同时存在于多个副本中
- 每个主分片和其副本分片不能同时存在于同一个节点上,所以最低的可用配置是两个节点互为主备(当某一节点宕机后,可保证数据的完整性)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-shiG1zSo-1656855298160)(/Users/armin/Desktop/截屏2022-06-23 下午10.01.18.png)]
主分片:存放原始数据,支持数据的读写
副本分片(具有数据的查询能力,副本本非越多越好):主分片的备份,不可进行数据的写入,仅可进行从主分片进行数据的同步;优点:提高数据的安全性、提高服务的可用性、提高并发查询的性能
在一个节点使用一台机器的情况下,每增加一台机器相当于可存放数据的扩容(横向扩容),且增加了副本提高了数据的高可用
集群
一个节点≠一台服务器(一台服务器可启动多个节点,生产环境中建议一台机器一个节点)
集群状态
健康状态
- Green:所有Primary和Replica均为active,集群健康
- Yellow:至少一个Replica不可用,但是所有Primary均为active,数据仍然是可以保证完整性的
- Red:至少有一个Primary为不可用状态,数据不完整,集群不可用
健康检查
/_cat/health?v
_cluster/health
ES与关系型数据库的结构对比
索引库(indices)---------------------------------Databases 数据库
类型(type)----------------------------------Table 数据表
文档(Document)--------------------------Row 行
字段(Field)---------------------Columns 列
基于REST风格的API
(1)创建索引:PUT /index?pretty //pretty可有可无
(2)查询索引:GET _cat/indices?v
(3)删除索引:DELETE /index?pretty
(4)插入数据:
PUT /index/_doc/id
{
Json数据
}
(5)
1) 全量替换 PUT
2) 指定字段更新
POST /product/_doc/1/_update
{
"doc":{
"name":"iPad mini" //修改的指定字段
}
}
or
POST /product/_update/1
{
"doc":{
"name":"iPad mini"
}
}
(6)删除数据 DELETE /index/type/id
Mapping
数据类型
① 常见类型
1) 数字类型:
long integer short byte double float half_float scaled_float unsigned_long
2) Keywords:
keyword:适用于索引结构化的字段,可以用于过滤、排序、聚合。keyword类型的字段只能通过精确值(exact value)搜索到。Id应该用keyword
constant_keyword:始终包含相同值的关键字字段
wildcard:可针对类似grep的通配符查询优化日志行和类似的关键字值
关键字字段通常用于排序, 汇总和Term查询,例如term
。
3) Dates(时间类型):包括date
和 date_nanos
4) alias:为现有字段定义别名。
6) range(区间类型):integer_range、float_range、long_range、double_range、date_range
7) text:当一个字段是要被全文搜索的,比如Email内容、产品描述,这些字段应该使用text类型。设置text类型以后,字段内容会被分析,在生成倒排索引以前,字符串会被分析器分成一个一个词项。text类型的字段不用于排序,很少用于聚合。(解释一下为啥不会为text创建正排索引[用于聚合]:大量堆空间,尤其是在加载高基数text字段时。字段数据一旦加载到堆中,就在该段的生命周期内保持在那里。同样,加载字段数据是一个昂贵的过程,可能导致用户遇到延迟问题。这就是默认情况下禁用字段数据的原因)
② 对象关系类型:
1) object:用于单个JSON对象
2) nested:用于JSON对象数组
3) flattened:允许将整个JSON对象索引为单个字段。
③ 结构化类型:
1) geo-point:纬度/经度积分
2) geo-shape:用于多边形等复杂形状
3) point:笛卡尔坐标点
2) shape:笛卡尔任意几何图形
④ 特殊类型:
1) IP地址:ip 用于IPv4和IPv6地址
2) completion:提供自动完成建议
3) tocken_count:计算字符串中令牌的数量
4) murmur3:在索引时计算值的哈希并将其存储在索引中
5) annotated-text:索引包含特殊标记的文本(通常用于标识命名实体)
6) percolator:接受来自query-dsl的查询
7) join:为同一索引内的文档定义父/子关系
8) rank features:记录数字功能以提高查询时的点击率。
9) dense vector:记录浮点值的密集向量。
10) sparse vector:记录浮点值的稀疏向量。
11) search-as-you-type:针对查询优化的文本字段,以实现按需输入的完成
12) histogram:histogram 用于百分位数聚合的预聚合数值。
13) constant keyword:keyword当所有文档都具有相同值时的情况的 专业化。
⑤ array(数组):在Elasticsearch中,数组不需要专用的字段数据类型。默认情况下,任何字段都可以包含零个或多个值,但是,数组中的所有值都必须具有 相同的数据类型。
⑥新增:
1) date_nanos:date plus 纳秒
2) features:
两种映射类型
查看映射:GET /product/_mapping
{
"product" : {
"mappings" : {
"properties" : {
"name" : {
"type" : "text", //text用于分词模糊查询
"fields" : {
"keyword" : {
"type" : "keyword", //keyword用于精确查询,name.keyword
"ignore_above" : 256 //name字段长度,超过256的部分自动丢弃
}
}
}
}
}
}
}
手动映射:PUT /product
{
"mappings": {
"properties": {
"name": { //name字段
"type": "text", //映射类型创建后无法修改,text不可修改为其他任意类型
"analyzer":"standard" //指定分词器,stadard为es默认分词器
}
}
}
}
映射参数(部分)
-
index:是否对创建对当前字段创建倒排索引,默认
true
,如果不创建索引,该字段不会通过索引被搜索到,但是仍然会在source
元数据中展示 -
analyzer:指定分析器(
character filter
、tokenizer
、Token filters
、ik[中文使用最多]
)-
GET _analyze { "analyzer": "standard", "text": "xiaomi nfc phone" //查询text文本使用standard分词器的分词结果 }
-
-
doc_values:为了提升排序和聚合效率,默认
true
,如果确定不需要对字段进行排序或聚合,也不需要通过脚本访问字段值,则可以禁用doc
值以节省磁盘空间(不支持text
和annotated_text
) -
enable:是否创建倒排索引,可以对字段操作,也可以对索引操作,如果不创建索引,让然可以检索并在
_source
元数据中展示,谨慎使用,该状态无法修改-
PUT my_index
-
{ "mappings": { "enabled": false } }
-
-
fielddata:查询时内存数据结构,在首次用当前字段聚合、排序或者在脚本中使用时,需要字段为
fielddata
数据结构,并且创建倒排索引保存到堆中(消耗JVM
内存通常禁止使用) -
norms:是否禁用评分,不用做检索或评分应该置为
false
(该字段会造成一定的性能下降,在filter
和聚合字段上应该禁用) -
null_value:为null值设置默认值
-
search_analyzer:设置单独的查询时分析器
搜索查询(Query DSL)
相关度评分:_score
概念:相关度评分用于对搜索结果排序,评分越高则认为其结果和搜索的预期值相关度越高,即越符合搜索预期值。在7.x
之前相关度评分默认使用TF/IDF
算法计算而来,7.x
之后默认为BM25
。在核心知识篇不必关心相关评分的具体原理,只需知晓其概念即可
排序:相关度评分为搜索结果的排序依据,默认情况下评分越高,则结果越靠前
元数据:_source
-
禁用_source:
-
好处:节省存储开销
-
坏处:
- 不支持update、update_by_query和reindex API。
- 不支持高亮。
- 不支持reindex、更改mapping分析器和版本升级。
- 通过查看索引时使用的原始文档来调试查询或聚合的功能。
- 将来有可能自动修复索引损坏。
总结:如果只是为了节省磁盘,可以压缩索引比禁用_source更好。
-
-
数据源过滤器:
Including:结果中返回哪些field
Excluding:结果中不要返回哪些field,不返回的field不代表不能通过该字段进行检索,因为元数据不存在不代表索引不存在
-
在mapping中定义过滤:支持通配符,但是这种方式不推荐,因为mapping不可变
PUT product { "mappings": { "_source": { "includes": [ "name", "price" ], "excludes": [ "desc", "tags" ] } } }
-
常用过滤规则
"_source": "false", "_source": "obj.*", "_source": [ "obj1.\*", "obj2.\*" ], "_source": { "includes": [ "obj1.\*", "obj2.\*" ], "excludes": [ "*.description" ] }
-
Query String
GET /product/_search?q=name:P50 #分词查询name包含P50的数据
GET /product/_search?q=P50 #分词查询所有字段包含P50的数据,不支持分词的字段P50作为全匹配
全文检索
-
match:查询包含某个
term
(词)的数据GET product/_search { "query": { "match": { "name": "xiaomi nfc phone" //检索product索引中出现过:xiaomi、nfc、phone或组合词汇的所有数据,排序根据_score评分进行排序,匹配度越高评分越高,词频越高评分越高 } } }
-
matc_all:查询所有,类似:
GET product/_search
GET product/_search { "query": { "match_all": {} } }
-
multi_match:多字段查询条件
GET product/_search { "query": { "multi_match": { "query": "phone Inc", //包含phone或Inc或phone Inc的数据 "fields": ["name", "company"] //name、company字段包含以上数据 } } }
-
match_phrase:短语查询
GET product/_search { "query": { "match_phrase": { "name": "xiaomi phone" //检索name包含xiaomi phone的数据 } } }
精准匹配
-
term
GET product/_search { "query": { "term": { "name": "xiaomi phone" //检索name完全相等xiaomi phone的数据(xiaomi phone没有被分词或分词为完整的xiaomi phone则可检索出);name type=text【被分词】无法查询出该数据 } } }
-
term
和match_phrase
区别:match_phrase
会将检索关键词分词,match_phrase
的分词结果必须在被检索字段的分词中都包含,而且顺序必须相同,而且默认必须都是连续的;term
搜索不会将搜索词分词 -
term
和keyword
区别 :term
是对于搜索词不分词,keyword
是字段类型,是对于source data
中的字段值不分词GET product/_search { "query": { "term": { "name.keyword": "xiaomi phone" //name type如为text类型,其子类型keyword type=keyword,则能将该全匹配的数据搜索出来 } } }
-
-
terms:检索词项列表中任意项匹配的结果
GET product/_search { "query": { "terms": { "tags": ["lowbee", "gongjiaoka"] //检索tags字段包含lowbee或者gongjiaka } } }
-
range:范围查找
GET product/_search { "query": { "range": { "price": { "gte": 10, "lte": 20 //检索price>=10 && price<=20的数据 } } } } GET product/_search { "query": { "range": { "date": { "time_zone": "+08:00", //结果date时区加8个小时如:2022-06-26T00:00:00 -> 2022-06-26T08:00:00 "gte": "now-1d/d", //date>=yesterday "lte": "now/d" //date<=tody } } } }
过滤器(filter)
用于先将结果筛选出来再进行排序等处理
query/filter区别:filter
是结果导向的而query
是过程导向;query
倾向于当前文档和查询的语句的相关度
而filter
倾向于当前文档和查询的条件是不是相符
;即在查询过程中,query
是要对查询的每个结果计算相关性得分的,而filter
不会;另外filter
有相应的缓存机制,可以提高查询效率
GET /product/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"name": "phone" //检索评分相同的name包含phone分词的数据
}
}
}
}
}
组合查询(Bool Query)
bool:可以组合多个查询条件,bool查询也是采用more_matches_is_better的机制,因此满足must和should子句的文档将会合并起来计算分值
- must:必须满足子句(查询)必须出现在匹配的文档中,并将有助于得分。
- filter:过滤器 不计算相关度分数,cache☆子句(查询)必须出现在匹配的文档中。但是不像 must查询的分数将被忽略。Filter子句在filter上下文中执行,这意味着计分被忽略,并且子句被考虑用于缓存。
- should:可能满足 or子句(0个或多个条件)应出现在匹配的文档中。
- must_not:必须不满足 不计算相关度分数 not子句(查询)不得出现在匹配的文档中。子句在过滤器上下文中执行,这意味着计分被忽略,并且子句被视为用于缓存。由于忽略计分,0因此将返回所有文档的分数。
GET population/_search
{
"query": {
"bool": {
"filter": [
"range": {
"age": {
"lte": 17 //首先从人口索引中过滤到非未成年人
}
}
],
"must": [
{
"match": {
"name": "王五" //再从过滤后的人口中匹配 name包含王五 的人
}
}
]
}
}
}
//该查询优化了查询,假设人口索引共14亿条,先更具年龄过滤(可以提交查询效率)去除成年人,再从未成年中找到王五
minimum_should_match:参数指定should返回的文档必须匹配的子句的数量或百分比。如果bool查询包含至少一个should子句,而没有must或 filter子句,则默认值为1。否则,默认值为0
GET product/_search
{
"_source": false,
"query": {
"bool": {
"filter": [
{
"range": {
"price": {
"lte": "10000"
}
}
}
],
"should": [
{
"match_phrase": {
"name": "nfc phone"
}
},
{
"match": {
"name": "erji"
}
},
{
"bool": {
"must": [
{
"range": {
"price": {
"gte": 900,
"lte": 3000
}
}
}
]
}
}
],
"minimum_should_match": 2 //filter过滤后should条件中的条件,至少需要满足两个条件
}
}
}
聚合查询(Aggregations)
持续更新中…