SpringBoot集成ElasticSearch(配置类版本)

SpringBoot集成ElasticSearch(配置类版本)

项目结构图

在这里插入图片描述

配置文件

  1. pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>xc-framework-parent</artifactId>
            <groupId>com.xuecheng</groupId>
            <version>1.0-SNAPSHOT</version>
            <relativePath>../xc-framework-parent/pom.xml</relativePath>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>xc-service-search</artifactId>
        <dependencies>
            <dependency>
                <groupId>com.xuecheng</groupId>
                <artifactId>xc-framework-model</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <dependency>
                <groupId>com.xuecheng</groupId>
                <artifactId>xc-framework-common</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <dependency>
                <groupId>com.xuecheng</groupId>
                <artifactId>xc-service-api</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.elasticsearch.client</groupId>
                <artifactId>elasticsearch-rest-high-level-client</artifactId>
                <version>6.8.9</version>
            </dependency>
            <dependency>
                <groupId>org.elasticsearch</groupId>
                <artifactId>elasticsearch</artifactId>
                <version>6.8.9</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-io</artifactId>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
            </dependency>
        </dependencies>
    
    </project>
    
  2. application.yml

    server:
      port: ${port:40100}
    spring:
      application:
        name: xc-search-service
    xuecheng:
      elasticsearch:
        hostlist: ${eshostlist:127.0.0.1:9200} #多个结点中间用逗号分隔
    
  3. logback-spring.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <configuration>
        <!--定义日志文件的存储地址,使用绝对路径-->
        <property name="LOG_HOME" value="/Users/xiaoge/Downloads/CMSPROJECT/logs"/>
    
        <!-- Console 输出设置 -->
        <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
                <charset>utf8</charset>
            </encoder>
        </appender>
    
        <!-- 按照每天生成日志文件 -->
        <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!--日志文件输出的文件名-->
                <fileNamePattern>${LOG_HOME}/xc.%d{yyyy-MM-dd}.log</fileNamePattern>
            </rollingPolicy>
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
            </encoder>
        </appender>
    
        <!-- 异步输出 -->
        <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
            <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
            <discardingThreshold>0</discardingThreshold>
            <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
            <queueSize>512</queueSize>
            <!-- 添加附加的appender,最多只能添加一个 -->
            <appender-ref ref="FILE"/>
        </appender>
    
    
        <logger name="org.apache.ibatis.cache.decorators.LoggingCache" level="DEBUG" additivity="false">
            <appender-ref ref="CONSOLE"/>
        </logger>
        <logger name="org.springframework.boot" level="DEBUG"/>
        <root level="info">
            <!--<appender-ref ref="ASYNC"/>-->
            <appender-ref ref="FILE"/>
            <appender-ref ref="CONSOLE"/>
        </root>
    </configuration>
    

配置类

  1. ElasticsearchConfig

    package com.xuecheng.search.config;
    
    import org.apache.http.HttpHost;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RestHighLevelClient;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @author Administrator
     * @version 1.0
     **/
    @Configuration
    public class ElasticsearchConfig {
    
        @Value("${xuecheng.elasticsearch.hostlist}")
        private String hostlist;
    
        @Bean
        public RestHighLevelClient restHighLevelClient(){
            //解析hostlist配置信息
            String[] split = hostlist.split(",");
            //创建HttpHost数组,其中存放es主机和端口的配置信息
            HttpHost[] httpHostArray = new HttpHost[split.length];
            for(int i=0;i<split.length;i++){
                String item = split[i];
                httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
            }
            //创建RestHighLevelClient客户端
            return new RestHighLevelClient(RestClient.builder(httpHostArray));
        }
    
        //项目主要使用RestHighLevelClient,对于低级的客户端暂时不用
        @Bean
        public RestClient restClient(){
            //解析hostlist配置信息
            String[] split = hostlist.split(",");
            //创建HttpHost数组,其中存放es主机和端口的配置信息
            HttpHost[] httpHostArray = new HttpHost[split.length];
            for(int i=0;i<split.length;i++){
                String item = split[i];
                httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
            }
            return RestClient.builder(httpHostArray).build();
        }
    
    }
    

启动类

  1. SearchApplication

    package com.xuecheng.search;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.domain.EntityScan;
    import org.springframework.context.annotation.ComponentScan;
    
    /**
     * @author Administrator
     * @version 1.0
     **/
    @SpringBootApplication
    @EntityScan("com.xuecheng.framework.domain.search")//扫描实体类
    @ComponentScan(basePackages={"com.xuecheng.api"})//扫描接口
    @ComponentScan(basePackages={"com.xuecheng.search"})//扫描本项目下的所有类
    @ComponentScan(basePackages={"com.xuecheng.framework"})//扫描common下的所有类
    public class SearchApplication {
    
        public static void main(String[] args) throws Exception {
            SpringApplication.run(SearchApplication.class, args);
        }
    
    }
    
    

测试模块

  1. TestElasticSearch

    package com.xuecheng.search;
    
    import org.elasticsearch.action.DocWriteResponse;
    import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
    import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
    import org.elasticsearch.action.delete.DeleteRequest;
    import org.elasticsearch.action.delete.DeleteResponse;
    import org.elasticsearch.action.get.GetRequest;
    import org.elasticsearch.action.get.GetResponse;
    import org.elasticsearch.action.index.IndexRequest;
    import org.elasticsearch.action.index.IndexResponse;
    import org.elasticsearch.action.search.SearchRequest;
    import org.elasticsearch.action.search.SearchResponse;
    import org.elasticsearch.action.support.master.AcknowledgedResponse;
    import org.elasticsearch.action.update.UpdateRequest;
    import org.elasticsearch.action.update.UpdateResponse;
    import org.elasticsearch.client.IndicesClient;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RestHighLevelClient;
    import org.elasticsearch.client.indices.CreateIndexResponse;
    import org.elasticsearch.common.settings.Settings;
    import org.elasticsearch.common.text.Text;
    import org.elasticsearch.common.xcontent.XContentType;
    import org.elasticsearch.index.query.*;
    import org.elasticsearch.rest.RestStatus;
    import org.elasticsearch.search.SearchHit;
    import org.elasticsearch.search.SearchHits;
    import org.elasticsearch.search.builder.SearchSourceBuilder;
    import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
    import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
    import org.elasticsearch.search.sort.SortOrder;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @Author: 潇哥
     * @DateTime: 2020/12/3 下午6:08
     * @Description: 测试ElasticSearch
     */
    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class TestElasticSearch {
    
        @Autowired
        private RestHighLevelClient restHighLevelClient;
    
        @Autowired
        private RestClient restClient;
    
    
        @Test
        public void testCreateIndex() throws IOException {
            // 创建索引请求对象
            CreateIndexRequest createIndexRequest = new CreateIndexRequest("xc_course");
    
            // 设置分片, 副本
            createIndexRequest.settings(Settings.builder().put("number_of_shards","1").put("number_of_replicas","0"));
    
            // 创建映射
            createIndexRequest.mapping("doc","{\"properties\": {\"name\": {\"type\": \"keyword\"},\"description\": {\"type\": \"text\",\"analyzer\":\"ik_max_word\",\"search_analyzer\":\"ik_smart\"}, \"pic\":{\"type\":\"text\",\"index\":false},\"studymodel\":{\"type\":\"keyword\"} }}",XContentType.JSON);
    
            // 操作索引的客户端
            IndicesClient indicesClient = restHighLevelClient.indices();
    
            // 创建索引及映射关系
            CreateIndexResponse createIndexResponse = indicesClient.create(createIndexRequest);
    
            // 得到响应结果
            boolean acknowledged = createIndexResponse.isAcknowledged();
    
            System.out.println(acknowledged);
    
        }
    
    
        /**
         * 删除索引
         * @throws IOException
         */
        @Test
        public void testDeleteIndex() throws IOException {
            // 删除索引请求对象
            DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("xc_course");
    
            // 操作索引的客户端
            IndicesClient indicesClient = restHighLevelClient.indices();
    
            // 删除索引
            AcknowledgedResponse acknowledgedResponse = indicesClient.delete(deleteIndexRequest);
    
            // 得到响应
            boolean acknowledged = acknowledgedResponse.isAcknowledged();
    
            System.out.println(acknowledged);
    
        }
    
        /**
         * 添加文档
         */
        @Test
        public void testAddDoc() throws IOException {
            //准备json数据
            Map<String, Object> jsonMap = new HashMap<>();
            jsonMap.put("name", "spring cloud实战");
            jsonMap.put("description", "本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud 基础入门 3.实战Spring Boot 4.注册中心eureka。");
            jsonMap.put("studymodel", "201001");
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy‐MM‐dd HH:mm:ss");
            jsonMap.put("timestamp", dateFormat.format(new Date()));
            jsonMap.put("price", 5.6f);
    
            //索引请求对象
            IndexRequest indexRequest = new IndexRequest("xc_course", "doc"); //指定索引文档内容
    
            // 添加数据
            indexRequest.source(jsonMap);
    
            //索引响应对象
            IndexResponse indexResponse = restHighLevelClient.index(indexRequest);
    
            //获取响应结果
            DocWriteResponse.Result result = indexResponse.getResult();
            System.out.println(result);
        }
    
    
        /**
         * 查询文档
         * @throws IOException
         */
        @Test
        public void getDoc() throws IOException {
            // 创建get请求
            GetRequest getRequest = new GetRequest(
                    "xc_course",
                    "doc",
                    "AX5LKHYBrcb0-WfhRHh1");
            // 查询数据
            GetResponse getResponse = restHighLevelClient.get(getRequest);
            // 查看是否查询成功
            boolean exists = getResponse.isExists();
            // 获取查询数据
            Map<String, Object> sourceAsMap = getResponse.getSourceAsMap();
            System.out.println(sourceAsMap);
        }
    
    
        /**
         * 更新文档
         */
        @Test
        public void updateDoc() throws IOException {
            // 创建更新
            UpdateRequest updateRequest = new UpdateRequest("xc_course", "doc",
                    "AX5LKHYBrcb0-WfhRHh1");
            // 输入你要更新的字段数据
            Map<String, String> map = new HashMap<>();
            map.put("name", "spring cloud无敌");
            // 添加进类型
            updateRequest.doc(map);
            // 执行更新
            UpdateResponse update = restHighLevelClient.update(updateRequest);
            // 查看更新状态
            RestStatus status = update.status();
            System.out.println(status);
        }
    
    
        /**
         * 根据id删除文档
          * @throws IOException
         */
        @Test
        public void testDelDoc() throws IOException {
            //删除文档id
            String id = "__mapping";
            //删除索引请求对象
            DeleteRequest deleteRequest = new DeleteRequest("xc_course","doc",id);
    
            //响应对象
            DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest);
    
            //获取响应结果
            DocWriteResponse.Result result = deleteResponse.getResult();
            System.out.println(result);
        }
    
    
        /**
         * 搜索type下的所有记录
         */
        @Test
        public void testSearchAll() throws IOException {
    
            // 搜索请求对象
            SearchRequest searchRequest = new SearchRequest("xc_course");
    
            // 设置类型
            searchRequest.types("doc");
    
            // 搜索源构建对象
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    
            // 搜索全部
            searchSourceBuilder.query(QueryBuilders.matchAllQuery());
    
            // source源字段过滤
            searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
    
            // 设置搜索源
            searchRequest.source(searchSourceBuilder);
    
            // 执行搜索
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
    
            // 搜索匹配结果
            SearchHits hits = searchResponse.getHits();
    
            // 搜索总记录数
            long totalHits = hits.totalHits;
    
            // 匹配度较高的前N个文档
            SearchHit[] searchHits = hits.getHits();
    
            for (SearchHit hit : searchHits) {
                String index = hit.getIndex();
                String type = hit.getType();
                String id = hit.getId();
                float score = hit.getScore();
                String sourceAsString = hit.getSourceAsString();
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String name = (String) sourceAsMap.get("name");
                String studymodel = (String) sourceAsMap.get("studymodel");
    
                // 因为上面过滤了该字段, 所有该字段的数据是取不到的
                String description = (String) sourceAsMap.get("description");
                System.out.println(name);
                System.out.println(studymodel);
                System.out.println(description);
            }
    
        }
    
    
        /**
         * 搜索type下的当前页记录
         */
        @Test
        public void testSearchPage() throws IOException {
    
            // 搜索请求对象
            SearchRequest searchRequest = new SearchRequest("xc_course");
    
            // 设置类型
            searchRequest.types("doc");
    
            // 搜索源构建对象
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    
            // 搜索全部
            searchSourceBuilder.query(QueryBuilders.matchAllQuery());
    
            int page = 1;
            int size = 1;
            // 获取从那条记录开始
            int from = (page - 1) * size;
            // 从当前记录开始
            searchSourceBuilder.from(from);
            // 每页展示的记录数
            searchSourceBuilder.size(size);
    
            // source源字段过滤
            searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
    
            // 设置搜索源
            searchRequest.source(searchSourceBuilder);
    
            // 执行搜索
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
    
            // 搜索匹配结果
            SearchHits hits = searchResponse.getHits();
    
            // 搜索总记录数
            long totalHits = hits.totalHits;
    
            // 匹配度较高的前N个文档
            SearchHit[] searchHits = hits.getHits();
    
            for (SearchHit hit : searchHits) {
                String index = hit.getIndex();
                String type = hit.getType();
                String id = hit.getId();
                float score = hit.getScore();
                String sourceAsString = hit.getSourceAsString();
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String name = (String) sourceAsMap.get("name");
                String studymodel = (String) sourceAsMap.get("studymodel");
                // 因为上面过滤了该字段, 所有该字段的数据是取不到的
                String description = (String) sourceAsMap.get("description");
                System.out.println(name);
                System.out.println(studymodel);
                System.out.println(description);
            }
    
        }
    
    
        /**
         * TermQuery: 精确查询,在搜索时会整体匹配关键字,不再将关键字分词
         */
        @Test
        public void testTermQuery() throws IOException {
    
            // 搜索请求对象
            SearchRequest searchRequest = new SearchRequest("xc_course");
    
            // 设置类型
            searchRequest.types("doc");
    
            // 搜索源构建对象
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    
            // 搜索精准查询, 不分词
            searchSourceBuilder.query(QueryBuilders.termQuery("name","spring"));
    
            // source源字段过滤
            searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
    
            // 设置搜索源
            searchRequest.source(searchSourceBuilder);
    
            // 执行搜索
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
    
            // 搜索匹配结果
            SearchHits hits = searchResponse.getHits();
    
            // 搜索总记录数
            long totalHits = hits.totalHits;
    
            // 匹配度较高的前N个文档
            SearchHit[] searchHits = hits.getHits();
    
            for (SearchHit hit : searchHits) {
                String index = hit.getIndex();
                String type = hit.getType();
                String id = hit.getId();
                float score = hit.getScore();
                String sourceAsString = hit.getSourceAsString();
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String name = (String) sourceAsMap.get("name");
                String studymodel = (String) sourceAsMap.get("studymodel");
                // 因为上面过滤了该字段, 所有该字段的数据是取不到的
                String description = (String) sourceAsMap.get("description");
                System.out.println(name);
                System.out.println(studymodel);
                System.out.println(description);
            }
    
        }
    
    
        /**
         * TermsQuery: 根据id精确匹配
         */
        @Test
        public void testTermsQuery() throws IOException {
    
            // 搜索请求对象
            SearchRequest searchRequest = new SearchRequest("xc_course");
    
            // 设置类型
            searchRequest.types("doc");
    
            // 搜索源构建对象
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    
            String[] values = new String[] {"1", "2"};
    
            // 搜索精准查询, 不分词
            searchSourceBuilder.query(QueryBuilders.termsQuery("_id",values));
    
            // source源字段过滤
            searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
    
            // 设置搜索源
            searchRequest.source(searchSourceBuilder);
    
            // 执行搜索
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
    
            // 搜索匹配结果
            SearchHits hits = searchResponse.getHits();
    
            // 搜索总记录数
            long totalHits = hits.totalHits;
    
            // 匹配度较高的前N个文档
            SearchHit[] searchHits = hits.getHits();
    
            for (SearchHit hit : searchHits) {
                String index = hit.getIndex();
                String type = hit.getType();
                String id = hit.getId();
                float score = hit.getScore();
                String sourceAsString = hit.getSourceAsString();
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String name = (String) sourceAsMap.get("name");
                String studymodel = (String) sourceAsMap.get("studymodel");
                // 因为上面过滤了该字段, 所有该字段的数据是取不到的
                String description = (String) sourceAsMap.get("description");
                System.out.println(name);
                System.out.println(studymodel);
                System.out.println(description);
            }
    
        }
    
    
        /**
         * MatchQuery: 即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索
         *
         * query:搜索的关键字,对于英文关键字如果有多个单词则中间要用半角逗号分隔,而对于中文关键字中间可以用 逗号分隔也可以不用。
         *
         * operator:or 表示 只要有一个词在文档中出现则就符合条件,and表示每个词都在文档中出现则才符合条件
         */
        @Test
        public void testMatchQuery() throws IOException {
    
            // 搜索请求对象
            SearchRequest searchRequest = new SearchRequest("xc_course");
    
            // 设置类型
            searchRequest.types("doc");
    
            // 搜索源构建对象
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    
            // 搜索字符串分词, operator为or(或)
            searchSourceBuilder.query(QueryBuilders.matchQuery("description", "spring java").operator(Operator.AND));
    
            // source源字段过滤
            searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
    
            // 设置搜索源
            searchRequest.source(searchSourceBuilder);
    
            // 执行搜索
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
    
            // 搜索匹配结果
            SearchHits hits = searchResponse.getHits();
    
            // 搜索总记录数
            long totalHits = hits.totalHits;
    
            // 匹配度较高的前N个文档
            SearchHit[] searchHits = hits.getHits();
    
            for (SearchHit hit : searchHits) {
                String index = hit.getIndex();
                String type = hit.getType();
                String id = hit.getId();
                float score = hit.getScore();
                String sourceAsString = hit.getSourceAsString();
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String name = (String) sourceAsMap.get("name");
                String studymodel = (String) sourceAsMap.get("studymodel");
                // 因为上面过滤了该字段, 所有该字段的数据是取不到的
                String description = (String) sourceAsMap.get("description");
                System.out.println(name);
                System.out.println(studymodel);
                System.out.println(description);
            }
    
        }
    
    
        /**
         * MatchQuery: 即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索
         *
         * query:搜索的关键字,对于英文关键字如果有多个单词则中间要用半角逗号分隔,而对于中文关键字中间可以用 逗号分隔也可以不用。
         *
         * 设置"minimum_should_match": "80%"表示,三个词在文档的匹配占比为80%,即3*0.8=2.4,向上取整得2,表
         * 示至少有两个词在文档中要匹配成功
         */
        @Test
        public void testMatchQueryMinimumShouldMatch() throws IOException {
    
            // 搜索请求对象
            SearchRequest searchRequest = new SearchRequest("xc_course");
    
            // 设置类型
            searchRequest.types("doc");
    
            // 搜索源构建对象
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    
            // 搜索字符串分词, 百分比查询
            searchSourceBuilder.query(QueryBuilders.matchQuery("description", "spring开发框架").minimumShouldMatch("80%"));
    
            // source源字段过滤
            searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
    
            // 设置搜索源
            searchRequest.source(searchSourceBuilder);
    
            // 执行搜索
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
    
            // 搜索匹配结果
            SearchHits hits = searchResponse.getHits();
    
            // 搜索总记录数
            long totalHits = hits.totalHits;
    
            // 匹配度较高的前N个文档
            SearchHit[] searchHits = hits.getHits();
    
            for (SearchHit hit : searchHits) {
                String index = hit.getIndex();
                String type = hit.getType();
                String id = hit.getId();
                float score = hit.getScore();
                String sourceAsString = hit.getSourceAsString();
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String name = (String) sourceAsMap.get("name");
                String studymodel = (String) sourceAsMap.get("studymodel");
                // 因为上面过滤了该字段, 所有该字段的数据是取不到的
                String description = (String) sourceAsMap.get("description");
                System.out.println(name);
                System.out.println(studymodel);
                System.out.println(description);
            }
    
        }
    
    
        /**
         * multiQuery,一次可以匹配多个字段
         * minimumShouldMatch: 匹配的百分比
         * field: 设置字段, 扩大权重
         *      字段: 指定要设置权重的字段
         *      boost: 匹配多个字段时可以提升字段的boost(权重)来提高得分
         * @throws IOException
         */
        @Test
        public void testMultiMatchQuery() throws IOException {
    
            // 搜索请求对象
            SearchRequest searchRequest = new SearchRequest("xc_course");
    
            // 设置类型
            searchRequest.types("doc");
    
            // 搜索源构建对象
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    
            // 一次可以匹配多个字段, name, description
            searchSourceBuilder.query(QueryBuilders.multiMatchQuery("spring css", "name","description").minimumShouldMatch("50%").field("name",10));
    
            // source源字段过滤
            searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
    
            // 设置搜索源
            searchRequest.source(searchSourceBuilder);
    
            // 执行搜索
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
    
            // 搜索匹配结果
            SearchHits hits = searchResponse.getHits();
    
            // 搜索总记录数
            long totalHits = hits.totalHits;
    
            // 匹配度较高的前N个文档
            SearchHit[] searchHits = hits.getHits();
    
            for (SearchHit hit : searchHits) {
                String index = hit.getIndex();
                String type = hit.getType();
                String id = hit.getId();
                float score = hit.getScore();
                String sourceAsString = hit.getSourceAsString();
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String name = (String) sourceAsMap.get("name");
                String studymodel = (String) sourceAsMap.get("studymodel");
                // 因为上面过滤了该字段, 所有该字段的数据是取不到的
                String description = (String) sourceAsMap.get("description");
                System.out.println(name);
                System.out.println(studymodel);
                System.out.println(description);
            }
    
        }
    
    
        /**
         * 布尔查询对应于Lucene的BooleanQuery查询,实现将多个查询组合起来
         *
         * must:文档必须匹配must所包括的查询条件,相当于 “AND”
         * should:文档应该匹配should所包括的查询条件其 中的一个或多个,相当于 "OR"
         * must_not:文档不能匹配must_not所包括的该查询条件,相当于“NOT”
         *
         *
         * @throws IOException
         */
        @Test
        public void testBooleanQuery() throws IOException {
    
            // 搜索请求对象
            SearchRequest searchRequest = new SearchRequest("xc_course");
    
            // 设置类型
            searchRequest.types("doc");
    
            // 搜索源构建对象
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    
            // 定义MultiMatchQueryBuilder
            MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring css", "name", "description").minimumShouldMatch("50%").field("name", 10);
    
            // 在定义termQueryBuilder
            TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("studymodel", "201001");
    
            // 在定义boolQueryBuilder
            BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
    
            // 把之前定义的查询条件, 添加到boolQueryBuilder的must里
            boolQueryBuilder.must(multiMatchQueryBuilder);
            boolQueryBuilder.must(termQueryBuilder);
    
            // 添加boolQueryBuilder的查询条件
            searchSourceBuilder.query(boolQueryBuilder);
    
            // source源字段过滤
            searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
    
            // 设置搜索源
            searchRequest.source(searchSourceBuilder);
    
            // 执行搜索
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
    
            // 搜索匹配结果
            SearchHits hits = searchResponse.getHits();
    
            // 搜索总记录数
            long totalHits = hits.totalHits;
    
            // 匹配度较高的前N个文档
            SearchHit[] searchHits = hits.getHits();
    
            for (SearchHit hit : searchHits) {
                String index = hit.getIndex();
                String type = hit.getType();
                String id = hit.getId();
                float score = hit.getScore();
                String sourceAsString = hit.getSourceAsString();
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String name = (String) sourceAsMap.get("name");
                String studymodel = (String) sourceAsMap.get("studymodel");
                // 因为上面过滤了该字段, 所有该字段的数据是取不到的
                String description = (String) sourceAsMap.get("description");
                System.out.println(name);
                System.out.println(studymodel);
                System.out.println(description);
            }
    
        }
    
    
        /**
         * Filter: 过虑是针对搜索的结果进行过虑,过虑器主要判断的是文档是否匹配,不去计算和判断文档的匹配度得分,所以过
         * 虑器性能比查询要高,且方便缓存,推荐尽量使用过虑器去实现查询或者过虑器和查询共同使用
         *
         * range: 范围过虑,保留大于等于60 并且小于等于100的记录。
         *
         * term: 项匹配过滤, 保留studymodel等于"201001"的记录
         *
         * @throws IOException
         */
        @Test
        public void testFilter() throws IOException {
    
            // 搜索请求对象
            SearchRequest searchRequest = new SearchRequest("xc_course");
    
            // 设置类型
            searchRequest.types("doc");
    
            // 搜索源构建对象
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    
            // 定义MultiMatchQueryBuilder
            MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring css", "name", "description").minimumShouldMatch("50%").field("name", 10);
    
            // 在定义boolQueryBuilder
            BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
    
            // 把之前定义的查询条件, 添加到boolQueryBuilder的must里
            boolQueryBuilder.must(multiMatchQueryBuilder);
    
            // 定义过滤器
            // 过滤出studymodel字段为201001的记录
            boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel", "201001"));
            // 过滤出, price字段值, 大于80小于100的记录
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(80).lte(100));
    
            // 添加boolQueryBuilder的查询条件
            searchSourceBuilder.query(boolQueryBuilder);
    
            // source源字段过滤
            searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
    
            // 设置搜索源
            searchRequest.source(searchSourceBuilder);
    
            // 执行搜索
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
    
            // 搜索匹配结果
            SearchHits hits = searchResponse.getHits();
    
            // 搜索总记录数
            long totalHits = hits.totalHits;
    
            // 匹配度较高的前N个文档
            SearchHit[] searchHits = hits.getHits();
    
            for (SearchHit hit : searchHits) {
                String index = hit.getIndex();
                String type = hit.getType();
                String id = hit.getId();
                float score = hit.getScore();
                String sourceAsString = hit.getSourceAsString();
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String name = (String) sourceAsMap.get("name");
                String studymodel = (String) sourceAsMap.get("studymodel");
                // 因为上面过滤了该字段, 所有该字段的数据是取不到的
                String description = (String) sourceAsMap.get("description");
                System.out.println(name);
                System.out.println(studymodel);
                System.out.println(description);
            }
    
        }
    
    
        /**
         * Sort: 可以在字段上添加一个或多个排序,支持在keyword、date、float等类型上添加,text类型的字段上不允许添加排序
         * @throws IOException
         */
        @Test
        public void testSort() throws IOException {
    
            // 搜索请求对象
            SearchRequest searchRequest = new SearchRequest("xc_course");
    
            // 设置类型
            searchRequest.types("doc");
    
            // 搜索源构建对象
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    
    
            // 在定义boolQueryBuilder
            BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
    
            // 过滤出, price字段值, 大于80小于100的记录
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(80).lte(100));
    
            // 添加boolQueryBuilder的查询条件
            searchSourceBuilder.query(boolQueryBuilder);
    
            // 定义排序字段
            searchSourceBuilder.sort("studymodel", SortOrder.DESC);
            searchSourceBuilder.sort("price", SortOrder.ASC);
    
            // source源字段过滤
            searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
    
            // 设置搜索源
            searchRequest.source(searchSourceBuilder);
    
            // 执行搜索
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
    
            // 搜索匹配结果
            SearchHits hits = searchResponse.getHits();
    
            // 搜索总记录数
            long totalHits = hits.totalHits;
    
            // 匹配度较高的前N个文档
            SearchHit[] searchHits = hits.getHits();
    
            for (SearchHit hit : searchHits) {
                String index = hit.getIndex();
                String type = hit.getType();
                String id = hit.getId();
                float score = hit.getScore();
                String sourceAsString = hit.getSourceAsString();
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String name = (String) sourceAsMap.get("name");
                String studymodel = (String) sourceAsMap.get("studymodel");
                // 因为上面过滤了该字段, 所有该字段的数据是取不到的
                String description = (String) sourceAsMap.get("description");
                System.out.println(name);
                System.out.println(studymodel);
                System.out.println(description);
            }
    
        }
    
    
        /**
         * Highlight: 高亮显示可以将搜索结果一个或多个字突出显示,以便向用户展示匹配关键字的位置
         * @throws IOException
         */
        @Test
        public void testHighlight() throws IOException {
    
            // 搜索请求对象
            SearchRequest searchRequest = new SearchRequest("xc_course");
    
            // 设置类型
            searchRequest.types("doc");
    
            // 搜索源构建对象
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    
            // source源字段过滤
            searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
    
            // 定义MultiMatchQueryBuilder
            MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("开发框架", "name", "description").minimumShouldMatch("50%").field("name", 10);
    
            // 在定义boolQueryBuilder
            BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
    
            // 添加搜索条件到 must中
            boolQueryBuilder.must(multiMatchQueryBuilder);
    
            // 过滤出, price字段值, 大于80小于100的记录
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(0).lte(100));
    
            // 添加boolQueryBuilder的查询条件
            searchSourceBuilder.query(boolQueryBuilder);
    
            // 定义排序字段
            searchSourceBuilder.sort("price", SortOrder.ASC);
    
            // 高亮设置
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            // 设置前缀
            highlightBuilder.preTags("<tag>");
            // 设置后缀
            highlightBuilder.postTags("</tag>");
            // 设置高亮字段
            highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
            // 把highlightBuilder添加到条件里
            searchSourceBuilder.highlighter(highlightBuilder);
    
            // 设置搜索源
            searchRequest.source(searchSourceBuilder);
    
            // 执行搜索
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
    
            // 搜索匹配结果
            SearchHits hits = searchResponse.getHits();
    
            // 搜索总记录数
            long totalHits = hits.totalHits;
    
            // 匹配度较高的前N个文档
            SearchHit[] searchHits = hits.getHits();
    
            for (SearchHit hit : searchHits) {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String name = (String) sourceAsMap.get("name");
    
                // 获取高亮信息
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
    
                if (highlightFields != null) {
                    // 取出高亮字段内容
                    HighlightField highlightField = highlightFields.get("name");
    
                    if (highlightField == null) {
                        continue;
                    }
    
                    // 获取内容
                    Text[] texts = highlightField.getFragments();
    
                    StringBuilder stringBuilder = new StringBuilder();
    
                    for (Text text : texts) {
                        stringBuilder.append(text.toString());
                    }
    
                    name = stringBuilder.toString();
                }
    
                String studymodel = (String) sourceAsMap.get("studymodel");
                // 因为上面过滤了该字段, 所有该字段的数据是取不到的
                String description = (String) sourceAsMap.get("description");
                System.out.println(name);
                System.out.println(studymodel);
                System.out.println(description);
            }
    
        }
    
    
    }
    
    
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只因为你温柔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值