知世故而不世故

D摇成成成


漫漫人生路,走走又停停。

Elasticsearch实战(干货)

Elasticsearch 说明

一、基础概念

一个ES集群可以包含多个索引(数据库),每个索引又包含了很多类型(表),类型中包含了很多文档(行),每个文档使用 JSON 格式存储数据,包含了很多字段(列)。

  1. INDEX

    说明:Elastic 会索引所有字段,经过处理后写入一个反向索引(Inverted Index)。查找数据的时候,直接查找该索引。

    所以,Elastic 数据管理的顶层单位就叫做 Index(索引)。它是单个数据库的同义词。每个 Index (即数据库)的名字必须是小写。

  2. Document

    说明:Index 里面单条的记录称为 Document(文档)。许多条 Document 构成了一个 Index。Document 使用 JSON 格式表示。

  3. TYPE

    说明:Document 可以分组,比如流转实例这个 Index 里面,可以按业务线(订单和大客户),也可以按步骤属性分组(流转和不流转)。这种分组就叫做 Type,它是虚拟的逻辑分组,用来过滤 Document。

  4. MAPPING

    说明
    ES的mapping非常类似于静态语言中的数据类型:声明一个变量为int类型的变量, 以后这个变量都只能存储int类型的数据。同样的, 一个number类型的mapping字段只能存储number类型的数据。同语言的数据类型相比,mapping还有一些其他的含义。
    mapping不仅告诉ES一个field中是什么类型的值, 它还告诉ES如何索引数据以及数据是否能被搜索到。

    当你的查询没有返回相应的数据, 你的mapping很有可能有问题。当你拿不准的时候, 直接检查你的mapping。

    "chatmessage": {
        "_source": {
          "enabled": false
        },
        "_all": {
          "enabled": false
        },
        "properties": {
          "messageText": {
            "analyzer": "ik_max_word",
            "type": "keyword"
          },      
          "speakerSurName": {
            "index": "not_analyzed",
            "type": "string"
          },
          "creatorUserId": {
            "type": "long"
          },
          "creationTime": {
            "format": "strict_date_optional_time||epoch_millis",
            "type": "date"
          }
        }
      }
    
    _source:字段默认是存储(true)的。

    什么情况下不用保留_source字段?

    如果某个字段内容非常多,
    业务只需要能对该字段进行搜索,最后返回文档id,查看文档内容会再次到Mysql中取数据,
    把大字段的内容存在Elasticsearch中只会增大索引,
    这一点文档数量越大结果越明显,如果一条文档节省几KB,放大到亿万级的量结果也是非常可观的。

    _all:能让你在不知道要查找的内容是属于哪个具体字段的情况下进行搜索,
    {
      "query": {
        "match": {
          "_all": "666"
        }
      }
    }
    
    String类型设置(7+版本以上去掉了这个属性,直接用text和keyworld)

    not_analyzed:搜索的时候不进行分词,所以理解为精确查找。

    analyzed:字段被索引,会做分词,可搜索。反过来,如果需要根据某个字段进行搜索,index属性就应该设置为analyzed
    no:字段不写入索引,当然也就不能搜索。反过来,有些业务要求某些字段不能被搜索,那么index属性设置为no即可。

    详情见:https://blog.csdn.net/napoay/article/details/62233031

二、前期准备

  • ES和传统数据库的对比
    • 优点

      ES分布式搜索,传统数据库遍历式搜索
      ES采用倒排索引,传统数据库采用B+树索引
      ES免费,完全开源;传统数据库部分免费

  • 缺点

    ES没有用户验证和权限控制
    ES没有事务的概念,不支持回滚,误删不能恢复
    写入后不会马上搜索到 中间会间隔1s

  • 结合工作举例

    例如,要计算出2.38亿会员中有多少80后的已婚的上海男士。

    传统数据库执行时间: 5个小时左右

    ES执行时间:1分钟

  • ES的特性

    官网的介绍: https://www.elastic.co/cn/products/elasticsearch

    速度快、易扩展、弹性、灵活、操作简单、多语言客户端、X-Pack、hadoop/spark强强联手、开箱即用。

    • **分布式:**横向扩展非常灵活
    • **全文检索:**基于lucene的强大的全文检索能力;
    • **近实时搜索和分析:**数据进入ES,可达到近实时搜索,还可进行聚合分析
    • **高可用:**容错机制,自动发现新的或失败的节点,重组和重新平衡数据
    • **模式自由:**ES的动态mapping机制可以自动检测数据的结构和类型,创建索引并使数据可搜索。
    • **RESTful API:**JSON + HTTP
  • ES数据为何是安全的

    es对数据的保障主要是依赖分片和拷贝的机制。

    • 分片:
      1)允许你水平分割/扩展你的内容容量。

      2)允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量。

    • 复制:
      1)在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上。

      2)扩展你的搜索量/吞吐量,因为搜索可以在所有的复制上并行运行。

      es_index

四、案例教程

  • Spring Coould 使用Es

    • 在pom导入ES架包

               <!-设置Es版本号>
                <properties>
                    <parent-project.version>0.0.1-SNAPSHOT</parent-project.version>
                    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
                    <facade.version>0.0.1-SNAPSHOT</facade.version>
                    <elasticsearch.version>7.3.1</elasticsearch.version>
                </properties> 
      
       						<!-引入Es架包>
                  <dependency>
                      <groupId>org.elasticsearch</groupId>
                      <artifactId>elasticsearch</artifactId>
                      <version>${elasticsearch.version}</version>
                  </dependency>
      
                  <dependency>
                      <groupId>org.elasticsearch.client</groupId>
                      <artifactId>elasticsearch-rest-client</artifactId>
                      <version>${elasticsearch.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>org.elasticsearch.client</groupId>
                      <artifactId>elasticsearch-rest-high-level-client</artifactId>
                      <version>${elasticsearch.version}</version>
                </dependency>
      
    • 在domain里面新增pom

    		<dependency>
    			<groupId>org.elasticsearch</groupId>
    			<artifactId>elasticsearch</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.elasticsearch.client</groupId>
    			<artifactId>elasticsearch-rest-client</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.elasticsearch.client</groupId>
    			<artifactId>elasticsearch-rest-high-level-client</artifactId>
    	</dependency>
    
    • 添加启动类

      @Configuration
      public class ElasticSearchConfig {
          @Value("172.16.20.1")
          private String esHost ;
      
          @Value("9800")
          private Integer esPort;
      
          @Bean(destroyMethod = "close")
          public RestHighLevelClient client() {
      
              RestHighLevelClient client = new RestHighLevelClient(
                      RestClient.builder(new HttpHost(esHost,esPort,"http")));
              return client;
          }
      }
      
    • 引入Helper类

      public interface IEsCommonHelper<T extends BaseEs> {
          /**
           * 根据Id获取数据
           * @param tClass t对应的类 如 A.class
           * @param id
           * @param indexName
           * @return
           */
          T getById(Class<T> tClass,int id, String indexName) throws IOException;
      
          /**
           * 根据Id删除数据
           * @param id
           * @param indexName
           * @return
           */
          void delById(int id,String indexName);
      
          /**
           * 更新数据
           * @param esObject
           * @param indexName
           */
          void  save(T esObject,String indexName);
      
          /**
           * 批量更新数据
           * @param tClass t对应的类 如 A.class
           * @param objects
           *
           * */
          void updateObjects(Class<T> tClass, List<T> objects,String indexName) throws Exception;
      
          /**
           * 批量新增ES数据
           * @param esObjectList
           * @param indexName
           */
          void bulkInsert(List<T> esObjectList,String indexName);
      
          /**
           * 条件分页查询
           * @param tClass t对应的类 如 A.class
           * @param searchSourceBuilder
           * @param indexName
           * @return
           */
          EsPaggerData<T> searchPage(Class<T> tClass, SearchSourceBuilder searchSourceBuilder, String indexName);
      }
      
      
    
    > 在更新的时候,如果是long类型,并且等于0的时候 设置成更新前的值。
    
    1.matchQuery(String name,Object  text)
    
    matchQuery("filedname","value")匹配单个字段,匹配字段名为filedname,值为value的文档
    
    //单个匹配,搜索name为jack的文档
    
    QueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "jack");
    
    2.multiMatchQuery(Object text, String... fieldNames)
    
    多个字段匹配某一个值
    
    //搜索name中或interest中包含有music的文档(必须与music一致)
    
    QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("music","name", "interest");
    
    3.wildcardQuery()模糊查询
    
    模糊查询,?匹配单个字符,*匹配多个字符
    
    //搜索名字中含有jack文档(name中只要包含jack即可)
    
    WildcardQueryBuilder queryBuilder = QueryBuilders.wildcardQuery("name","*jack*");
    
    4.BoolQueryBuilder进行复合查询
    
    4.1使用must
    
    //模糊查询并搜索名字中含有jack的文档
    WildcardQueryBuilder queryBuilder1 = QueryBuilders.wildcardQuery( "name", "*jack*");
    
    //模糊查询并搜索interest中含有read的文档
    WildcardQueryBuilder queryBuilder2 = QueryBuilders.wildcardQuery( "interest", "*read*");
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    //name中必须含有jack,interest中必须含有read,相当于and
    boolQueryBuilder.must(queryBuilder1);
    boolQueryBuilder.must(queryBuilder2);
    
    输出结果:name中必须含有jack,interest中必须含有read
    
    4.2 使用 should
    
    WildcardQueryBuilder queryBuilder1 = QueryBuilders.wildcardQuery("name", "*jack*");//搜索名字中含有jack的文档
    WildcardQueryBuilder queryBuilder2 = QueryBuilders.wildcardQuery("interest", "*read*");//搜索interest中含有read的文档
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    //name中含有jack或者interest含有read,相当于or
    boolQueryBuilder.should(queryBuilder1);
    boolQueryBuilder.should(queryBuilder2);
    
    输出结果:name中含有jack或者interest中含有read的都将被匹配
    

五、参考文档

https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html
https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html

1.为什么要用es。
2.除了es有考虑其他的查询组件嘛
3.es的优势是啥。
4.es怎么做到这样优势的。

es基础介绍

elasticsearch之常见错误

es的mapping介绍

es与数据库的比较

es面试题

更早的文章

办公软件目录(软件)

百度云盘:https://pan.baidu.com/s/1ouScdNQQWMIC8444zwJbFA密码:ceizMac软件1.软件目录:https://mp.weixin.qq.com/s/mVxJYiGrfselJx1b9XdvYwWin软件拓展idea破解地址:https://zhile.…

继续阅读