zoukankan      html  css  js  c++  java
  • 《ElasticSearch入门》优雅的揭开面纱

    一、顾名思义:

      Elastic:灵活的;Search:搜索引擎

    二、官方简介:

      Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。

    三、优势:

      天然分片,天然集群,天然索引--->正如他的名字一样,查询速度快,是他最大的优势。

    四、业务场景:

      在大数据场景下,面对千万级数据,我们一般都会在mysql上进行分库分表。比如我们根据公司名称查询公司详细信息,

    数据库已经被分成若干个,表分成若干个,我们是不知道具体在哪个库,哪个表。分库分表后,每个表都有一个唯一标识id,

    这个id可以解析出库表的后缀。那怎么根据名称获取这个id呢,有一种思路就是公司名称的md5,然后解析到指定的索引库表,

    然后我们就可以查询到id,再根据id获取其他信息。按照传统模式,我们需要从mysql查询两次,第一次从索引库查询id,

    然后根据id获取其他信息。面对亿级数据,每过一次数据库,效率都要打折扣。

      于是es携带其天生的全文高速检索优势正式亮相:有以下3种方案:

        1、将索引库整合导入es,我们优先从es中进行精确或者模糊匹配,然后再去mysql查询具体数据。

        2、将所有数据库整合导入es,直接从es查询。

        3、每次先从es查询,es没有从mysql查询,然后更新到es。

      大概分析下各自的优缺点:

        1、可以大大提高检索效率,但需要消耗巨大存储与内存空间。

        2、可以高效的支持精确与模糊查询,空间与效率折中。中庸之道。

        3、业务环节变多,风险多,查询速度较低。

    五、掀起盖头来(探索底层的奥秘)

      很遗憾,这篇文章是掀不起来了,多次提笔,却发现自己还是没真正领悟,无法用自己语言通俗的写出来,

    后续专门写一篇《掀起ElasticSearch的盖头》

    六、重要知识点:

    6.1、核心数据类型:

      text:文本,默认会采用指定分词器进行分词,然后按照分词进行倒排索引。

      keyword:一个串就是一个整体,直接按照keyword进行倒排索引。

    6.2、分词:

      分词是模糊匹配的基础,比如“中华人民共和国”,不同的分词器拆分不同,假设会将其拆分成“中华”,“人民”,“共和国”。

    于是当我们利用“中华“进行模糊查询时,中华人民共和国就会被我们检索到。

    6.3、常用工具:

      Kibana(ELK中的K):功能强大,酷炫。使用起来没有eshead的”德福感“(丝滑)

      es_head:小而精悍,你要的他都有。

    七、事上炼:

      SpringBoot+ElasticSearch

    7.1、es数据来源:

      7.1.1、利用logstash导入

      7.1.2、利用java api导入

    7.2、es操作:

      ES 7.0版本中将弃用TransportClient客户端,已证明存在性能问题,目前大都采用:ElasticsearchTemplate

    7.3、例子

    7.3.1、es中的结构

    "name": {
      "type": "text",     #支持text,用于模糊匹配
      "fields": {
         "keyword": {
            "ignore_above": 256,
            "type": "keyword"     #支持keyword,用户精确匹配
        }
      }
    }
    

    7.3.2、模糊匹配

      1、将要查询的词,先进行分词,再进行匹配(MatchQuery)

      2、将要查询的词,作为一个整体,进行匹配(MatchPhraseQuery),主要用这种

    /**
     * 模糊匹配*/
    public List getEidsFromEs(String name) {
        QueryBuilder queryBuilder = QueryBuilders.matchPhraseQuery(name, "name");
        Pageable pageable =  PageRequest.of(0, 10);  //分页
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withIndices("index")
                .withTypes("_doc")
                .withPageable(pageable)
                .build();
        AggregatedPage<doc> docs = template.queryForPage(searchQuery, doc.class);
        List<doc> eids = docs.getContent();        
        return eids;
    } 

    7.3.3精确匹配场景

      1、单条件,单字段(条件:”中华“,查询es中name字段)->termQuery

      2、单条件,多字段(条件:”中华“,查询es中name,ename,com_name字段)->termQuery+boolQuery

      3、多条件,单字段(条件:”中华“,”中国“,查询es中name)->termsQuery

      4、多条件,多字段(条件:”中华“,”中国“,查询es中name,ename,com_name字段)->termQuery+boolQuery

    /**
     * <单条件,单字段>模糊匹配*/
    public List getEidsFromEs(String name) {
        name = name + ".keyword";   //这很关键,增加后缀,启用keyword精确匹配
        QueryBuilder queryBuilder = QueryBuilders.termQuery(name, "name");
        Pageable pageable =  PageRequest.of(0, 10);  //分页
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withIndices("index")
                .withTypes("_doc")
                .withPageable(pageable)
                .build();
        AggregatedPage<doc> docs = template.queryForPage(searchQuery, doc.class);
        List<doc> eids = docs.getContent();        
        return eids;
    }

      

    /**
     * <单条件,多字段>模糊匹配*/
    Map<String, Object> boolQueryMap = new HashMap<>();
    Map<String, Object> boolQuery = new HashMap<>();
    for (String key : keys) {
        boolQueryMap.put(key+".keyword", name);
        boolQuery.put(key+".keyword", Constants.SHOULD);
    }
    SearchQueryBean searchQueryBean = new SearchQueryBean()
            .setIndex(Constants.CBI_COMMON_INDEX).setType(Constants.CBI_COMMON_DOC)
            .setBoolQuery(boolQuery).setBoolQueryMap(boolQueryMap)
            .setPageNum(0).setPageSize(10)
            .setClazz(EsIndexDocument.class);
    BoolQueryBuilder booleanBoolQuery = QueryBuilders.boolQuery();
    Iterator var3 = searchQueryBean.boolQueryMap.keySet().iterator();
    while(var3.hasNext()) {
        Object key = var3.next();
        if (searchQueryBean.getBoolQuery().containsKey(key)) {
           QueryBuilder queryBuilder = QueryBuilders.termQuery(key.toString(), searchQueryBean.boolQueryMap.get(key));
           Method method = booleanBoolQuery.getClass().getMethod(searchQueryBean.getBoolQuery().get(key).toString(), QueryBuilder.class);
           method.invoke(booleanBoolQuery, queryBuilder);
         }
    }
    NativeSearchQuery searchQuery = this.buildNativeSearchQuery(searchQueryBean, booleanBoolQuery);
    return this.elasticsearchTemplate.queryForPage(searchQuery, searchQueryBean.getClazz());

     ps:

      写到这里,文章已经到了尾声,此篇文章,主要讲述了es的入门步骤,也仅仅是入门,学习还是在个人。

      对文中有任何异议,可随时留言或者邮箱反馈:wpt191@163.com,您的反馈是我们共同进步的催化剂。

      还是那句话:学一门,爱一门,精一门,从知道到做到,还需要不停的努力与付出。

  • 相关阅读:
    Linux基础命令(一)
    You've made choice
    protege推理
    字符编码
    第二次作业
    数据类型-集合set
    数据类型-元组&字典
    数据类型-列表
    数据类型-数值&字符串
    流程控制之for循环
  • 原文地址:https://www.cnblogs.com/weipt0106/p/13138371.html
Copyright © 2011-2022 走看看