Elasticsearch 学习总结

一、ES简介

1.什么是es?

Elasticsearch是一个基于Apache Lucene的开源搜索引擎,通过简易的API来隐藏Lucene的复杂性。ES的基本结构包括,Cluster集群(由n个节点组成),Node实例节点,Index索引(一系列documents的集合),Shard分片(索引的数据是分配到各个分片的),Replica备份节点(相应有Primay Shard主分片)
Elasticsearch是面向文档型数据库,一条数据在这里就是一个文档,用JSON作为文档序列化的格式

2.ES不是什么?
ES不是数据库,不是可靠的数据存储系统。
ES不是实时系统,数据写入成功只是translog成功,类似mysql的binlog,同理删除数据也不是实时的
ES不是一个强一致性的系统,但是最终一致性

二、ES与数据库的对比

关系数据库 ⇒ 数据库 ⇒ 表 ⇒ 行 ⇒ 列(Columns)
Elasticsearch ⇒ 索引(Index) ⇒ 类型(type) ⇒ 文档(Docments) ⇒ 字段(Fields)
Elasticsearch7.X之后 type默认_doc 之后版本将移除

三、基本数据类型

1.核心数据类型(Core datatypes)

字符型(String datatype):string (6.x之后改为keyword 和 text )
字符型(String datatype):text
数字型(Numeric datatypes):long, integer, short, byte, double, float
日期型(Date datatype):date
布尔型(Boolean datatype):boolean
二进制型(Binary datatype):binary

2.复杂数据类型(Complex datatypes)

数组类型(Array datatype):数组类型不需要专门指定数组元素的type,例如:
字符型数组: [ “one”, “two” ]
整型数组:[ 1, 2 ]
数组型数组:[ 1, [ 2, 3 ]] 等价于[ 1, 2, 3 ]
对象数组:[ { “name”: “Mary”, “age”: 12 }, { “name”: “John”, “age”: 10 }]
对象类型(Object datatype): object 用于单个JSON对象;
嵌套类型(Nested datatype): nested 用于JSON数组;

3.地理位置类型(Geo datatypes)

地理坐标类型(Geo-point datatype): geo_point 用于经纬度坐标;
地理形状类型(Geo-Shape datatype): geo_shape 用于类似于多边形的复杂形状;

4.特定类型(Specialised datatypes)

IPv4 类型(IPv4 datatype): ip 用于IPv4 地址;
Completion 类型(Completion datatype): completion 提供自动补全建议;
Token count 类型(Token count datatype): token_count 用于统计做了标记的字段的index数目,该值会一直增加,不会因为过滤条件而减少。

四、分片和节点数合理分配

如果索引A总文件大小是300G,改怎么定制方案了?

1、保证每一个分片数据大小在30GB左右
2、每一个节点最多存放一个分片
3、节点数大于等于分片数
根据建议,至少需要十个分片。
结果: 建10个数据节点,Mapping 指定分片数为 10,满足每一个节点一个分片,每一个分片大小30G左右。
SN(分片数) = IS(索引大小) / 30
NN(节点数) = SN(分片数) + MNN(主节点数[无数据]) + NNN(负载节点数)
分片数取决于你的es集群有多大,以及你想要达到的并发程度。
副本数量取决于你想要达到多高的数据可用性和你有多少存储空间可用
在Elasticsearch中,每个查询在每个分片的单个线程中执行。 但是,可以并行处理多个分片,对同一分片也可以进行多个查询和聚合, 如果不涉及缓存,则最小查询延迟将取决于数据、查询类型以及分片的大小。 查询大量小的分片将使每个分片的处理速度更快,但是需要按顺序排队和处理更多的任务,它不一定比查询较少数量的较大分片更快。 如果存在多个并发查询,则拥有大量小分片也会降低查询吞吐量。

五、倒排索引和正排索引

1、倒排索引
doc1: hello world you and me
doc2: hi, world, how are you

2、正排索引
doc1: { “name”: “jack”, “age”: 27 }
doc2: { “name”: “tom”, “age”: 30 }
document name age
doc1 jack 27
doc2 tom 30

搜索的时候,要依靠倒排索引;
排序的时候,需要依靠正排索引,每个document的每个field,然后进行排序,所谓的正排索引,其实就是doc values
在建立索引的时候,会建立倒排索引,以供搜索用;也会建立正排索引,也就是doc values,以供排序,聚合,过滤等操作使用
doc values是被保存在磁盘上的,此时如果内存足够,os会自动将其缓存在内存中,性能还是会很高;如果内存不足够,os会将其写入磁盘上

六、查询规范

1、search type不要用dfs_query_then_fetch(打分),用query_then_fetch(es默认查询)
2、尽可能的用filter
3、使用scroll/scan,相当于数据库的游标方式代替深分页(size=10&from=10000)
4、不要使用post filter,post filter的内部实现相当于数据库的扫表,因此非常非常慢
5、不要使用delete-by-query
6、控制返回,不需要的字段不要获取
“_source”: [“first_name”, “age”]

七、注意项

1、为什么不用from+size做深度翻页?

clien发送一个搜索请求,每个shard都包含部份数据,所以每个shard上都有可能包含搜索的结果,都会接到到请求
接收到请求的每个shard都会去构建各自的from+size大小的本地priority query 每个shard都会构建一个10000 + 10 大小的priority query
每个shard将自已的10010条数据
每个shard将自已的10010条数据返回给coordinate node,然后将所有shard的from + size进行合并,合并成一个from+size大小的priority query 进行全局排序后放入自已的query
coordinate query 将合并的query取出当前需要的那一页数据进行返回 比如从10W页起 则返回100010
分页太深每个shard都返回大量数据给coordinate node,消耗大量的带宽内存和CPU

2、为什么相同几个节点不放多条业务线?
Node Query Cache,早期版本也叫做filter cache。 Node级别,被所有shard共享。 主要用于缓存在filter上下文里执行的Query,比如Range Query。 缓存的是压缩过的bitset,对应满足Query条件的docID列表。 这个缓存有一些智能的地方: 比如不是所有的Query都会被缓存,而是记录最近256个Query,只有重用过的,才会被挑选出来放到缓存; 对于小的segment会跳过不缓存; 5.1 以后对于term query完全不缓存; 新写入的文档会增量加入到bitset,而无需反复重建整个bitset。
文件系统缓存,也就是Linux OS page cache。 ES对于索引的访问是通过memory mapped file来访问的,经常访问的segment,只要没有合并,再次访问时可以直接从page cache里读取。 所以索引里被经常访问的热数据片段,等同于内存读取。

3、es字段使用驼峰命名

八、ES可优化的点

1、禁用不需要查询的字段将index设为false 减少内存开销,将不需要分词的字段设置为keyword,非使用区间数据将类型设为keyword,将数据预排序
2、ES集群各节点尽量不要和其他业务功能复用一台机器。
3、集群节点数:<=3,建议:所有节点的master:true, data:true。既是主节点也是路由节点。集群节点数:>3, 根据业务场景需要,建议:逐步独立出Master节点和协调/路由节点。
4、建议冷热数据分离
按照日期规划索引(可以实现历史数据秒删,便于冷热数据分开管理)
5、不要使用默认的Mapping
6、禁用swap
7、结合业务场景,大量使用filter过滤器
8、控制返回字段和结果
9、分页查询使用:from+size;遍历使用:scroll;并行遍历使用:scroll+slice,斟酌集合业务选型使用
10、禁用 wildcard模糊匹配

九、常用聚合查询使用案例

1.基本匹配查询(Basic Match Query)
基本匹配查询主要有两种形式:
(1)使用Search Lite API,并将所有的搜索参数都通过URL传递;
(2)使用Elasticsearch DSL,其可以通过传递一个JSON请求来获取结果。下面是在所有的字段中搜索带有"John"的结果

 curl -XGET 'localhost:9200/megacorp/employee/_search?q=John'

使用Query DSL来展示出上面一样的结果

curl -XGET 'localhost:9200/megacorp/_search' -d '{
    "query": {
        "multi_match" : {
            "query" : "John",
            "fields" : ["_all"]
        }
    }
}'

2.Multi-field Search
在一个搜索中查询多个 document field (比如使用同一个查询关键字同时在title和summary中查询),你可以使用multi_match查询,使用如下:

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '{
    "query": {
        "multi_match" : {
            "query" : "rock",
            "fields": ["about", "interests"]
        }
    }
}'

3.Boosting
使用同一个搜索请求在多个field中查询,你也许想提高某个field的查询权重,在下面的例子中,我们把interests的权重调成3,提高了其在结果中的权重,如下:

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '{
    "query": {
        "multi_match" : {
            "query" : "rock",
            "fields": ["about", "interests^3"]
        }
    }
}'

4. Bool Query
可以在查询条件中使用AND/OR/NOT操作符,布尔查询(Bool Query)。布尔查询可以接受一个must参数(等价于AND),一个must_not参数(等价于NOT),以及一个should参数(等价于OR)。比如,我想查询about中出现music或者climb关键字的员工,员工的名字是John,但姓氏不是smith,如下:

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '{
    "query": {
        "bool": {
                "must": {
                    "bool" : { 
                        "should": [
                            { "match": { "about": "music" }},
                            { "match": { "about": "climb" }} ] 
                    }
                },
                "must": {
                    "match": { "first_nale": "John" }
                },
                "must_not": {
                    "match": {"last_name": "Smith" }
                }
            }
    }
}'

5.Fuzzy Queries(模糊查询)
模糊查询可以在Match和 Multi-Match查询中使用以便解决拼写的错误,模糊度是基于Levenshteindistance计算与原单词的距离。使用如下:

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '{
    "query": {
        "multi_match" : {
            "query" : "rock climb",
            "fields": ["about", "interests"],
            "fuzziness": "AUTO"
        }
    },
    "_source": ["about", "interests", "first_name"],
    "size": 1
}'

我们将fuzziness的值指定为AUTO,其在term的长度大于5的时候相当于指定值为2,然而80%的人拼写错误的编辑距离(edit distance)为1,所有如果你将fuzziness设置为1可能会提高你的搜索性能

6.Wildcard Query(通配符查询)
通配符查询允许我们指定一个模式来匹配,而不需要指定完整的trem。?将会匹配如何字符;将会匹配零个或者多个字符。比如我们想查找所有名字中以J字符开始的记录,我们可以如下使用:

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '{
    "query": {
            "wildcard" : {
                "first_name" : "大唐*"
            }
        },
        "_source": ["first_name", "last_name"],
    "highlight": {
            "fields" : {
                "first_name" : {}
            }
        }
}'

7.Regexp Query(正则表达式查询)
ElasticSearch还支持正则表达式查询,此方式提供了比通配符查询更加复杂的模式。比如我们先查找作者名字以J字符开头,中间是若干个a-z之间的字符,并且以字符n结束的记录,可以如下查询:


curl -XGET 'localhost:9200/megacorp/employee/_search' -d '{
    "query": {
        "regexp" : {
            "first_name" : "J[a-z]*n"
        }
    },
    "_source": ["first_name", "age"],
    "highlight": {
        "fields" : {
            "first_name" : {}
        }
    }
}'

8. Match Phrase Query(匹配短语查询)
匹配短语查询要求查询字符串中的trems要么都出现Document中、要么trems按照输入顺序依次出现在结果中。在默认情况下,查询输入的trems必须在搜索字符串紧挨着出现,否则将查询不到。不过我们可以指定slop参数,来控制输入的trems之间有多少个单词仍然能够搜索到,如下所示:

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '{
    "query": {
        "multi_match": {
            "query": "climb rock",
            "fields": [
                "about",
                "interests"
            ],
            "type": "phrase",
            "slop": 3
        }
    } 
}'

9. Match Phrase Prefix Query(匹配短语前缀查询)
匹配短语前缀查询可以指定单词的一部分字符前缀即可查询到该单词,和match phrase query一样我们也可以指定slop参数;同时其还支持max_expansions参数限制被匹配到的terms数量来减少资源的使用,使用如下:

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '{
    "query": {
        "match_phrase_prefix": {
            "summary": {
                "query": "cli ro",
                "slop": 3,
                "max_expansions": 10
            }
        }
    },
    "_source": [
        "about",
        "interests",
        "first_name"
    ]
}'

10.Query String
query_string查询提供了一种手段可以使用一种简洁的方式运行multi_match queries, bool queries, boosting, fuzzy matching, wildcards, regexp以及range queries的组合查询。在下面的例子中,我们运行了一个模糊搜索(fuzzy search),搜索关键字是search algorithm,并且作者包含grant ingersoll或者tom morton。并且搜索了所有的字段,其中summary字段的权重为2:

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '{
    "query": {
        "query_string" : {
            "query": "(saerch~1 algorithm~1) AND (grant ingersoll) OR (tom morton)",
            "fields": ["_all", "summary^2"]
        }
    },
    "_source": [ "title", "summary", "authors" ],
    "highlight": {
        "fields" : {
            "summary" : {}
        }
    }
}'

11.Simple Query String(简单查询字符串)
simple_query_string是query_string的另一种版本,其更适合为用户提供一个搜索框中,因为其使用+/|/- 分别替换AND/OR/NOT,如果用输入了错误的查询,其直接忽略这种情况而不是抛出异常。使用如下:

curl -POST 'localhost:9200/megacorp/employee/_search' -d '{
    "query": {
        "simple_query_string" : {
        "query": "(saerch~1 algorithm~1) + (grant ingersoll) | (tom morton)",
        "fields": ["_all", "summary^2"]
        }
    },
    "_source": [ "title", "summary", "authors" ],
    "highlight": {
        "fields" : {
            "summary" : {}
        }
    }
}'

12.Term/Terms Query(使用)
搜索所有兴趣中有music的人如下:

curl -POST 'localhost:9200/megacorp/employee/_search' -d '{
    "query": {
        "term" : {
            "interests": "music"
        }
    }
  }'
或者
{
    "query": {
        "terms" : {
            "publisher": ["oreilly", "packt"]
        }
    }
}

13.Term Query - Sorted(使用)
查询排序

curl -XPOST 'localhost:9200/megacorp/employee/_search' -d '{
    "query": {
        "term" : {
            "interests": "music"
        }
    },
    "_source" : ["interests","first_name","about"],
    "sort": [
        { "publish_date": {"order":"desc"}},
        { "id": { "order": "desc" }}
    ]
}'

14.Range Query(范围查询)(使用)
范围查询可以应用于日期,数字以及字符类型的字段。
gte 大于等于 gt 大于

curl -XPOST 'localhost:9200/person/worker/_search?pretty' -d '{
    "query": {
        "range" : {
            "birthday": {
                "gte": "2017-02-01",
                "lte": "2017-05-01"
            }
        }
    }
  }'

15.Filter Query

curl -XGET "http://192.168.30.51:9200/r_pay_order/_search" -d'{
  "track_total_hits" : true,
  "query": {
    "bool": {
      "filter": [{
        "term": {
          "payType": "16"
        }
      },
      {
        "range": {
          "createTime": {
            "gte": "2019-05-01 13:58:03",
            "lte": "2019-08-09 14:58:03"
          }
        }
      }
      ]
    }
  }
  
}'

16.桶聚合
于根据根据payType分组查询出总数并求出amount总金额

curl -XGET "http://192.168.30.51:9200/r_pay_order/_search" -H 'Content-Type: application/json' -d'
{
  "track_total_hits" : true,
  "query": {
    "bool": {
      "filter": {
        "range": {
          "createTime": {
            "gte": "2019-05-01 13:58:03",
            "lte": "2019-08-09 14:58:03"
          }
        }
      }
    }
  },
  "size": 0,
   "aggs": {
    "group_count": {
      "terms": {"field": "payType"},
       "aggs":{
        "sum_amount":{
          "sum":{"field": "amount"}
        }
      }
    }
  }
}'
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于学习Elasticsearch,你可以按照以下步骤进行: 1. 首先,你可以从Docker Hub上获取Elasticsearch的镜像。你可以使用以下命令来拉取特定版本的Elasticsearch镜像: ``` docker pull docker.elastic.co/elasticsearch/elasticsearch:7.6.2 ``` 2. 接下来,你可以创建一个简单的Dockerfile来构建一个Elasticsearch容器。Dockerfile的内容可以参考以下示例: ``` FROM docker.elastic.co/elasticsearch/elasticsearch:7.6.2 COPY --chown=elasticsearch:elasticsearch elasticsearch.yml /usr/share/elasticsearch/config/ ``` 这个Dockerfile会将你的自定义配置文件`elasticsearch.yml`复制到Elasticsearch容***-analysis-ik`项目。该项目提供了一个支持中文分词的插件,你可以在以下链接找到它: ``` https://github.com/medcl/elasticsearch-analysis-ik ``` 你可以根据项目的文档和示例,自定义和配置分词器和分析器以满足你的需求。 通过上述步骤,你可以开始学习和使用Elasticsearch,并根据需要进行自定义配置和扩展。希望对你有所帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [ES(Elasticsearch)入门学习教程](https://blog.csdn.net/m0_55070913/article/details/124243790)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [ElasticSearch学习总结(基础篇,可学习,可复习)](https://blog.csdn.net/Gaowumao/article/details/124484971)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值