日志处理系统技术栈之Elasticsearch学习笔记

前言

我们生活在一个信息爆炸的时代,每天各种信息充斥的我们的大脑。我们要求这些海量的数据能够永久保存,而且在我们的用的时候也能快速检索到(我们这些贪婪的人类)。我们的技术进步就是来源于我们各种奇怪的新需求,正因为这般需求Elasticsearch诞生了。它能保存海量数据,检索速度快,提供分布式,提供全文搜索功能,即是我们输入的关键字不准确,也能搜索到想要的数据。总之,Elasticsearch好处多多,赶快学习吧!

1、为什么学习Elasticsearch?

    1、在海量的数据中执行搜索功能时,如果使用MySQL,效率太低

    2、如果关键字输入不准确,一样可以搜索到想要的数据。

    3、将搜索关键字,以红色的字体展示。

2、Elasticsearch介绍

    1、Java语言并且基于Lucene编写的搜索引擎框架

    2、提供分布式的全文搜索功能

    3、提供基于RESTFul风格的web接口

    4、官方客户端也对多种语言都提供了相应的API

Lucene本身就是一个搜索引擎的底层。

分布式:ES主要为了突出它的横向扩展能力

全文检索:将一段词语进行分词。(倒排索引)

应用广泛:GitHub、WIKI、京东等

3、Elasticsearch与Slor的区别:

    1、Slor在查询死数据时、速度相对ES更快。但是数据如果是实时改变的,Slor的速度会降低很多,ES的查询效率基本没有变化。

    2、Solr搭建基于需要依赖Zookeeper来帮助管理。ES本身就支持集群的搭建,不需要第三方的介入。

    3、最开始Solr的社区可以说是非常火爆的,针对国内的文档并不是很多。在ES出现之后,ES的社区火爆程度直线上升,ES的文档非常健全。

    4、ES对现在的云计算和大数据支持的特别好。

4、深分页Scroll

ES对from+size是有限制的,from和size二者之和不能超过1W

原理:

    from+size在查询数据的方式

          第一步:先将用户指定的关键字进行分词

          第二步:将词汇去分词库中进行检索,得到多个文档的ID。

          第三步:去各个分片中去拉去指定的数据,耗时较长。

          第四步:将数据根据score进行排序,耗时较长。

          第五步:根据from的值,将查询到的数据舍弃一部分。

          第六步:返回结果

    Scroll+size在ES中查询数据的方式:

          第一步:先将用户指定的关键字进行分词

          第二步:将词汇去分词库中进行检索,得到多个文档ID。

          第三步:将文档的ID存放在一个ES的上下文中。

          第四步:根据你指定的size去ES中检索指定的数据,拿完数据的文档ID,会从上下文中移除。

          第五步:如果需要下一页数据,直接去ES的上下文中,找后续的内容

          第六步:循环第四步和第五步。

    【*】Scroll查询方式,不适合做实时的查询。

5、倒排索引

解释:

  1. 将存放的数据以一定的方式进行分词,并将分词的内容存放到一个单独的分词库中。
  2. 当用户取查询数据时,会将用户的查询关键字进行分词,然后去分词库中匹配内容,最终得到数据的id标识。
  3. 根据id标识去存放数据的位置拉去指定数据。

6、ES的基本概念

  •   索引(index),分片,备份
ES服务中会创建多个索引
每个缩影默认被分成5个分片
每个分片存在至少一个备份分片
备份分片 不会帮助检索数据(当ES检索压力特别大的时候才,备份分片才会帮助检索数据)
备份的分片必须放在不同的服务器中
  • 类型(type)
一个索引下可以创建多个类型
PS:版本不同,类型的创建也不同
  • 文档(document)
一个类型下可以有多个文档,这个文档就相当于mysql表中的多行数据
  • 属性Field
一个文档中可以包含多个属性,类似于mysql 表中的一行数据有多个列

7、Elasticsearch的查询语法(RESTful 风格)

  • 这是ES查询语句的整体结构:

    {
        "query":{}, //查询的条件
        "from":0, //分页:从第几页开始
        "size":5, //每页显示几条数据
        "sort":[{},{}], //排序
        "highlight":{}, //高亮查询
        "aggs":"" //聚合查询
    }
  • 关于query里面的结构

  • 根据多个ID查询数据
    {
        “query”:{
              “ids”:{ 
                     "values": ["1","2","3"]
               }
         }
    }
  • term和terms查询
terms 和 term 查询的机制一样,搜索之前不会对你搜索的关键字进行分词,直接拿 关键字 去文档分词库中匹配内容       terms:是针对一个字段包含多个值
     term : where province =北京
     terms: where province = 北京  or  province =?  (类似于mysql 中的 in)
     也可针对 text,  只是在分词库中查询的时候不会进行分词 ​​​​​​
{
    "query" : {
          "term" : {
            "属性名": {
                   "value" : ""
             }
         },
          "terms" : {
            "属性名" : ["",""]
         }
     }
}
  • match和match_all查询

    match_all查询全部内容,不指定查询条件。

     match:指定一个Field 作为查询条件。

     布尔match 查询:基于一个field 匹配的内容,按照 and 或者or的方式连接

{
    "query":{
          "match":{
                 "属性名": ""
          },
           "match_all" : {},
            "match":{
                "属性名": {
                        # 既包含 战士 也包含 团队
           "query": "战士 团队",
           "operator": "and"
                 },
             }
     }
}
  • 其他查询说明:

multi_match:match 针对一个field 做检索,multi_math 针对多个field 进行检索,多个field对应一个文本。

prefix 查询:前缀查询,可以通过一个关键字去指定一个field 的前缀,从而查询到指定文档

fuzzy 查询:模糊查询,我们可以输入一个字符的大概,ES 可以根据输入的大概去匹配内容。查询结果不稳定

 wildcard 查询:通配查询,同mysql中的like 是一样的,可以在查询时,在字符串中指定通配符*和占位符?

rang 查询:范围查询,只针对数值类型,对一个field 进行大于或者小于的范围指定

regexp 查询:正则查询,通过你编写的正则表达式去匹配内容

                       Ps:prefix wildcard fuzzy 和regexp 查询效率比较低 ,在要求效率比较高时,避免使用

复合查询:复合过滤器,将你的多个查询条件 以一定的逻辑组合在一起,

  • must:所有条件组合在一起,表示 and 的意思    
  • must_not: 将must_not中的条件,全部都不匹配,表示not的意思
  • should:所有条件用should 组合在一起,表示or 的意思

boosting查询:可以帮助我们去影响查询后的score。

         positive:只有匹配上positive 查询的内容,才会被放到返回的结果集中

        negative: 如果匹配上了positive 也匹配上了negative, 就可以 降低这样的文档score.

         negative_boost:指定系数,必须小于1   0.5 

        关于查询时,分数时如何计算的:

              搜索的关键字再文档中出现的频次越高,分数越高

              指定的文档内容越短,分数越高。

              我们再搜索时,指定的关键字也会被分词,这个被分词的内容,被分词库匹配的个数越多,分数就越高。

filter查询:   
    query 查询:根据你的查询条件,去计算文档的匹配度得到一个分数,并根据分数排序,不会做缓存的。
    filter 查询:根据查询条件去查询文档,不去计算分数,而且filter会对经常被过滤的数据进行缓存。

{
     “query”:{
         “ids/term/terms/match/multi_match/prefix/fuzzy/wildcard/range/regexp”:{},
         “bool”:{
             “should”: [],
             “must_not”:[],
             “must”: [],
             “filter”:[{},{}]
         },
         “boosting”:{
             “positive”:{ “match”:{}},
             “negative”:{“match”:{}},
             “negative_boost”: 0.2 }
     }
}
  • 高亮查询

高亮查询就是用户输入的关键字,以一定特殊样式展示给用户,让用户知道为什么这个结果被检索出来
高亮展示的数据,本身就是文档中的一个field,单独将field以highlight的形式返回给用户
ES提供了一个highlight 属性,他和query 同级别。
     frament_size: 指定高亮数据展示多少个字符回来
     pre_tags:指定前缀标签<front color="red">
     post_tags:指定后缀标签 </font>

{
    "query" : {
        "match": {
              "属性名": ""
         }
     },
     "highlight" : {
        "fields" : {
            "属性名" : {}
         },
          "pre_tags":"<font color='red'>",
          "post_tags": "</font>",
          "fragment_size": 10 
     }
}
  • 聚合查询

    去重计数,cardinality 先将返回的文档中的一个指定的field进行去重,统计一共有多少条

    范围统计:统计一定范围内出现的文档个数,比如,针对某一个field 的值再0~100,100~200,200~300 之间文档出现的个数分别是多少

     范围统计 可以针对 普通的数值,针对时间类型,针对ip类型都可以响应。
     数值 rang    
     时间  date_rang     
     ip   ip_rang

     统计聚合:他可以帮你查询指定field 的最大值,最小值,平均值,平方和...

         使用 extended_stats

    其他聚合:查看官方文档

{
    "aggs" : {
          "自定义查询名(一般为agg)": {
               "聚合类型(cardinality,range,ip_range,extended_stats)" : {
                       "field": "属性名",
                        
                 }
         }
     }
}
  • 地图经纬度搜索

  ES 的地图检索方式

          geo_distance :直线距离检索方式

          geo_bounding_box: 以2个点确定一个矩形,获取再矩形内的数据

          geo_polygon:以多个点,确定一个多边形,获取多边形的全部数据

{
    "query": {
          "geo_distance" : {
                  //确定一个点
                 "location": {
                        "lat" : 39.95499,
                        "lon" : 116.434739
                  },
                   //半径长度
                   "distance": 2000,
                   //指定形状是圆形
                   "distance_type": "arc"
          },
      "geo_bounding_box":{
          "location":{
             "top_left":{
                  "lon":116.327805,
                  "lat":39.95499
              },
              "bottom_right":{
                  "lon": 116.363162,
                  "lat":39.938395
              }
          }
      },
     "geo_polygon":{
           "location":{
                 # 指定多个点确定 位置
             "points":[{
                 "lon":116.220296,
                 "lat":40.075013
               },{
                 "lon":116.346777,
                 "lat":40.044751
               },{
                 "lon":116.236106,
                 "lat":39.981533
               }]
           }
      }
     }
}

8、通过使用JavaAPI对ES进行操作

// 1.SearchRequest 查询操作/ DeleteByQueryRequest:删除操作/ IndexRequest 新增操作 / UpdateRequest 更新操作
     //DeleteByQueryRequest request = new DeleteByQueryRequest(index);
     //IndexRequest request = new IndexRequest(index,type,person.getId().toString());
     //UpdateRequest request = new UpdateRequest(index,type,"1");
     SearchRequest request= new SearchRequest(index);
     searchRequest.types(type);
// 2.指定查询条件
     SearchSourceBuilder builder = new SearchSourceBuilder();
     builder.query(QueryBuilders.matchAllQuery());
     //指定scroll信息,过期时间
     searchRequest.scroll(TimeValue.timeValueMinutes(1L));
     //  ES 默认只查询10条数据
     builder.size(20);
     builder.sort("fee", SortOrder.DESC);

     //组合查询
     BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
     boolBuilder.filter(QueryBuilders.termQuery("corpName","海尔智家公司"));
     builder.query(boolBuilder);

    //高亮查询
     HighlightBuilder highlightBuilder = new HighlightBuilder();
     highlightBuilder.field("smsContent",10)
        .preTags("<font colr='red'>")
        .postTags("</font>");
     builder.highlighter(highlightBuilder);
    
     //聚合查询 (范围统计)
     builder.aggregation(AggregationBuilders.range("agg").field("fee")
                    .addUnboundedTo(30)
                    .addRange(30,60)
                    .addUnboundedFrom(60));

     builder.aggregation(AggregationBuilders.extendedStats("agg").field("fee"));
    
    //聚合查询 (去重计数)
    builder.aggregation(AggregationBuilders.cardinality("provinceAgg")
                                           .field("province"));

     request.source(builder);

     
     
     //client.index(request, RequestOptions.DEFAULT);
     //client.delete(request, RequestOptions.DEFAULT)
     //client.update(request, RequestOptions.DEFAULT);
     client.search(request, RequestOptions.DEFAULT);

总结

这篇博文是我学习Elasticsearch的笔记,可能对Elasticsearch的知识点分享不够全面细致。任何技术学习的开始,对这个技术的认识都是浅薄的,不可能学习了几天就能获得几年的经验。这边博文只是Elasticsearch入门的第一步,目的就是对Elasticsearch有一个整体的认识和基本的使用,之后的就需要我们在使用中积累经验了。加油吧,少年!!

看到这里了,记得点赞+关注哦!!!谢谢

猜你喜欢

转载自blog.csdn.net/LookForDream_/article/details/108626247
今日推荐