SpringBoot集成ElasticSearch

作者: 我叫钱多多_ | 来源:发表于2018-09-12 16:57 被阅读13次

    1. ElasticSearch

    1.1 ElasticSearch的简单介绍

    ElasticSearch 是开源搜索平台领域的一个新成员。 ElasticSearch(简称 ES) 是一个基于 Lucene 构建的开源,分布式,RESTful 搜索引擎。 具有搜索实时、稳定、可靠和快速的特点,并且安装使用方便。 支持通过 HTTP 请求,使用 JSON 进行数据索引。

    1.2 ElasticSearch的一些概念的介绍

    (1). 索引: 一个索引就是一个拥有几分相似特征的文档的集合。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。在一个集群中,可以定义任意多的索引。索引名称必须要全部小写,也不能以下划线开头,不能包含逗号。类似于关系型数据库中的数据库;
    (2). 类型:在一个索引中,可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,通常,会为具有一组共同字段的文档定义一个类型,每一个类型都拥有自己的映射(mapping)或者结构定义,它们定义了当前类型下的数据结构,类似于数据库表中的列。划分时需要注意一些限制条件,例如不同的文档类型对同一字段不能设置为不同的字段类型;类似于关系型数据库中的的表;
    (3). 文档:一个文档是一个可被索引的基础信息单元。文档以JSON(JavascriptObject Notation)格式来表示,一个文档不只包含了数据。它还包含了元数据(metadata) —— 关于文档的信息。有三个元数据元素是必须存在的,它们是:id是一个字符串, _index 和 _type ,他们可以组合起来锁定Elasticsearch中一个特定的文档。

    1.3 ElasticSearch与关系型数据库的对照关系

    DB -> Databases -> Tables -> Rows -> Columns 
    ES -> Indices -> Types -> Documents -> Fields
    

    3.4 ElasticSearch中对索引的一些常用操作

    1. 获取Elasticsearch中所有的index:

    curl -XGET 'localhost:9200/_cat/indices?v&pretty'

    2. 获取某索引下所有的type:

    获取elasticsearch索引下所有的type定义
    curl -XGET 'localhost:9200/elasticsearch/_mapping'

    3. 删除索引:

    删除elasticsearch1索引
    curl -XDELETE 'localhost:9200/elasticsearch1?pretty'

    4. 删除某索引下的某type数据:

    删除索引elasticsearch下的article类型
    curl -XDELETE 'http://localhost:9200/elasticsearch/article/'

    5. 查看某索引的某type下所有的数据:

    查找elasticsearch索引中所有的类型为Company的数据
    http://localhost:9200/elasticsearch/Company/_search

    3.5 ElasticSearch所遇到过的问题

    1 当查询的时候如果没有设置from和size,那么默认只会查出10条,不是我们想要的果

    解决办法: 通过先查出总的条数,再将其值设置为size;

    2 查询多条数据时遇到过的问题:

    错误提示信息:Result window is too large
    解决方案: 主要是修改index.max_result_window参数,默认为10000
    命令:curl -XPUT http://127.0.0.1:9200/cmdb-now/_settings -d '{ "index" : { "max_result_window" : 100000000}}'

    3 各种版本与api不匹配的问题

    解决方式:上网找,以及测试api与版本

    1.6 ElasticSearch架构及其支持的客户端连接方式

    Es架构图

    方式一:REST API ,端口 9200:这种连接方式对应于架构图中的RESTful style API这一层,这种客户端的连接方式是RESTful风格的,使用http的方式进行连接

    方式二:Transport ,端口 9300:这种连接方式对应于架构图中的Transport这一层,这种客户端连接方式是直接连接ES的节点,使用TCP的方式进行连接;(ES7.0将会关闭Transport,8.0将完全删除,取而代之的是High Level REST Client)

    ElasticSearch提供了两个JAVA REST client 版本:
    Java Low Level REST Client: 低级别的REST客户端,通过http与集群交互,需自己编组请求JSON串,及解析响应JSON串。兼容所有ES版本。

    Java High Level REST Client: 高级别的REST客户端,基于低级别的REST客户端,增加了编组请求JSON串、解析响应JSON串等相关api。使用的版本需要保持和ES服务端的版本一致,否则会有版本问题。

    1.7 代码示例

        
        /**
         * @description: es工具类
         * @author: Guimu
         * @create: 2018/07/31 11:47:55
         **/
        @Component
        public class EsUtils {
            @Autowired
            private RestHighLevelClient client;
            private static final String CURRENT_MODEL_PACKAGE_NAME = "com.yy.elasticsearch.model.";
            private static final String DEFAULT_INDEX = "elasticsearch";
        
            /**
             * @Description: 根据Base 子类数据产生一个IndexRequest数据
             * @Param: [source]
             * @Return: org.elasticsearch.action.index.IndexRequest
             * @Author: Guimu
             * @Date: 2018/7/31  下午5:30
             */
            private IndexRequest indexRequestGenerater(Base source) {
                IndexRequest indexRequest = null;
                if (StringUtils.isEmpty(source.getIndex())) {
                    source.setIndex(DEFAULT_INDEX);
                }
                try {
                    String[] tempArr = source.getClass().getName().split("\\.");
                    source.setType(tempArr[tempArr.length - 1]);
                    indexRequest = new IndexRequest(source.getIndex(), source.getType());
                    indexRequest.source(JacksonUtil.getString(source), XContentType.JSON);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                return indexRequest;
            }
        
            /**
             * @Description: 批量存储接口, boolean  表示保存成功与否
             * @Param: [bases]
             * @Return: boolean
             * @Author: Guimu
             * @Date: 2018/7/31  下午5:32
             */
            public boolean batchSave(List<? extends Base> bases) {
                BulkRequest bulkRequest = new BulkRequest();
                bases.forEach(el -> bulkRequest.add(indexRequestGenerater(el)));
                boolean flag = false;
                try {
                    BulkResponse bulkItemResponses = client.bulk(bulkRequest);
                    flag = "created".equalsIgnoreCase(bulkItemResponses.getItems()[0].getResponse().getResult().name());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return flag;
            }
        
            /**
             * @Description: 保存单个索引文档数据
             * @Param: [source]
             * @Return: boolean
             * @Author: Guimu
             * @Date: 2018/7/31  下午2:05
             */
            public boolean singleSave(Base source) {
                IndexRequest singleRequest;
                boolean flag = false;
                try {
                    singleRequest = indexRequestGenerater(source);
                    IndexResponse indexResponse = client.index(singleRequest);
                    flag = "created".equalsIgnoreCase(indexResponse.getResult().name());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return flag;
            }
        
            /**
             * @Description: 模糊匹配名字, 精确匹配corpId
             * @Param: [name, corpId]
             * @Return: java.util.List<com.yy.elasticsearch.model.Base>
             * @Author: Guimu
             * @Date: 2018/7/31  下午2:21
             */
            public List<Base> queryLikeNameAndCorpId(String name, String type, Long corpId) {
                MatchPhraseQueryBuilder mb1 = QueryBuilders.matchPhraseQuery("corpId", corpId);
                MatchPhraseQueryBuilder mb2 = QueryBuilders.matchPhraseQuery("name", "*" + name + "*");
                QueryBuilder queryBuilder = QueryBuilders.boolQuery().must(mb1).must(mb2);
                SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
                searchSourceBuilder.query(queryBuilder);
                SearchRequest searchRequest = new SearchRequest(DEFAULT_INDEX);
                searchRequest.types(type);
                searchRequest.source(searchSourceBuilder);
                return baseQuery(searchRequest);
            }
        
            /**
             * @Description: 查找指定corpId和type的所有数据
             * @Param: [name, corpId]
             * @Return: java.util.List<com.yy.elasticsearch.model.Base>
             * @Author: Guimu
             * @Date: 2018/7/31  下午2:21
             */
            public List<Base> queryByCorpId(String type, Long corpId) {
                MatchPhraseQueryBuilder mb = QueryBuilders.matchPhraseQuery("corpId", corpId);
                QueryBuilder queryBuilder = QueryBuilders.boolQuery().must(mb);
                SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
                searchSourceBuilder.query(queryBuilder);
                SearchRequest searchRequest = new SearchRequest(DEFAULT_INDEX);
                searchRequest.types(type);
                searchRequest.source(searchSourceBuilder);
                return baseQuery(searchRequest);
            }
        
            /**
             * @Description: 查询该索引中, 指定type的所有数据
             * @Param: [index, type]
             * @Return: java.util.List<com.yy.elasticsearch.model.Base>
             * @Author: Guimu
             * @Date: 2018/7/31  下午6:06
             */
            public List<Base> findAll(String index, String type) {
                SearchRequest searchRequest = new SearchRequest(index);
                SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
                searchSourceBuilder.from(0);
                searchSourceBuilder.size(this.getCount(searchRequest).intValue());
                searchRequest.source(searchSourceBuilder);
                //查询全部xxxxx
                searchRequest.types(type);
                return baseQuery(searchRequest);
            }
        
            /**
             * @Description: 获取该查询请求的总条数total
             * @Param: [searchRequest]
             * @Return: java.lang.Long
             * @Author: Guimu
             * @Date: 2018/7/31  下午4:58
             */
            private Long getCount(SearchRequest searchRequest) {
                SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
                searchSourceBuilder.from(0);
                searchSourceBuilder.size(1);
                searchRequest.source(searchSourceBuilder);
                try {
                    SearchResponse response = client.search(searchRequest);
                    return response.getHits().getTotalHits();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return -1L;
            }
        
            /**
             * @Description: 私有的基础查询, 提高代码复用性
             * @Param: [searchRequest]
             * @Return: java.util.List<com.yy.elasticsearch.model.Base>
             * @Author: Guimu
             * @Date: 2018/7/31  下午6:15
             */
            private List<Base> baseQuery(SearchRequest searchRequest) {
                try {
                    SearchResponse response = client.search(searchRequest);
                    return Arrays.asList(response.getHits().getHits()).stream().map(el -> {
                        Map<String, Object> map = el.getSource();
                        Class clazz;
                        Base base = null;
                        try {
                            map.put("id", el.getId());
                            clazz = Class.forName(CURRENT_MODEL_PACKAGE_NAME + map.get("type").toString());
                            base = (Base) JacksonUtil.getObject(JacksonUtil.getString(map), clazz);
                        } catch (IOException | ClassNotFoundException e) {
                            e.printStackTrace();
                        }
                        return base;
                    }).collect(Collectors.toList());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
        
            /**
             * @Description: 基础删除接口, 支持Base的所有子类
             * @Param: [base]
             * @Return: boolean
             * @Author: Guimu
             * @Date: 2018/7/31  下午6:32
             */
            public boolean deleteBase(Base base) {
                DeleteRequest deleteRequest = new DeleteRequest(base.getIndex(), base.getType(), base.getId());
                boolean flag = false;
                try {
                    DeleteResponse deleteResponse = client.delete(deleteRequest);
                    flag = "deleted".equalsIgnoreCase(deleteResponse.getResult().name());
                    System.out.println(deleteResponse);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return flag;
            }
        
            /**
             * @Description: 此处传入的base的所有值都是全的,没有null值
             * @Param: [base]
             * @Return: boolean
             * @Author: Guimu
             * @Date: 2018/8/1  上午10:02
             */
            public boolean updateBase(Base base) {
                UpdateRequest updateRequest = new UpdateRequest(base.getIndex(), base.getType(), base.getId());
                boolean flag = false;
                try {
                    updateRequest.doc(JacksonUtil.getString(base), XContentType.JSON);
                    UpdateResponse updateResponse = client.update(updateRequest);
                    flag = "updated".equalsIgnoreCase(updateResponse.getResult().name());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return flag;
            }
        
            /**
             * @Description: 根据名字, type, corpId 进行精确查询Base数据,没找到则返回 null
             * @Param: [name, type, corpId]
             * @Return: com.yy.elasticsearch.model.Base
             * @Author: Guimu
             * @Date: 2018/8/1  上午9:35
             */
            public <T extends Base> T queryOneBase(String name, String type, Long corpId) {
                MatchPhraseQueryBuilder mb = QueryBuilders.matchPhraseQuery("corpId", corpId);
                MatchPhraseQueryBuilder mb1 = QueryBuilders.matchPhraseQuery("name", name);
                QueryBuilder queryBuilder = QueryBuilders.boolQuery().must(mb).must(mb1);
                SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
                searchSourceBuilder.query(queryBuilder);
                SearchRequest searchRequest = new SearchRequest(DEFAULT_INDEX);
                searchRequest.types(type);
                searchRequest.source(searchSourceBuilder);
                Base rebase = null;
                try {
                    rebase = baseQuery(searchRequest).get(0);
                } catch (NullPointerException e) {
                    e.printStackTrace();
                }
                Class<T> aClass = null;
                try {
                    aClass = (Class<T>) Class.forName(CURRENT_MODEL_PACKAGE_NAME + type);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
                return null == rebase ? null : aClass.cast(rebase);
            }
        
            public static String getDefaultIndex() {
                return DEFAULT_INDEX;
            }
        }
    

    相关文章

      网友评论

        本文标题:SpringBoot集成ElasticSearch

        本文链接:https://www.haomeiwen.com/subject/dvqbgftx.html