天天看点

Springboot 整合 ElasticSearch Demo

文章目录

    • 引入 ElasticSearch 依赖
    • 配置 ES 连接
    • Search Request
    • Search Demo
  • 引入 ElasticSearch 依赖

<!--   ElasticSearch 依赖     -->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.6.1</version>
</dependency>
           

运行起来报了一堆找不到类异常

Caused by: java.lang.ClassNotFoundException: org.elasticsearch.action.admin.cluster.repositories.cleanup.CleanupRepositoryRequest

Caused by: java.lang.NoClassDefFoundError: org/elasticsearch/action/admin/cluster/repositories/cleanup/CleanupRepositoryRequest
           

我用的

springboot

版本是

2.1.8.RELEASE

,用 Maven 查看依赖管理发现,ElasticSearch 版本居然是

6.4.3

Springboot 整合 ElasticSearch Demo

我不是指定了版本是 7.6.1 吗???

查看 pom.xml Effective POM for project,发现

Springboot 整合 ElasticSearch Demo

应该是这个版本的 springboot 默认指定了 6.4.3 版本的 ElasticSearch ,那我们在 properties 里重新指定 ES 的版本即可

<properties>
        <java.version>1.8</java.version>
        <elasticsearch.version>7.6.1</elasticsearch.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
           
  • 配置 ES 连接

    • application.yml

      文件添加配置:
    elasticsearch:
    host: 192.168.3.213
    port: 9200
    username:
    password:
               
    • 新建

      ElasticsearchConfig

      类:
    package xxx.common.configure;
    
    import org.apache.http.HttpHost;
    import org.apache.http.auth.AuthScope;
    import org.apache.http.auth.UsernamePasswordCredentials;
    import org.apache.http.client.CredentialsProvider;
    import org.apache.http.impl.client.BasicCredentialsProvider;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RestClientBuilder;
    import org.elasticsearch.client.RestHighLevelClient;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class ElasticsearchConfig {
        @Value("${elasticsearch.host}")
        private String host;
    
        @Value("${elasticsearch.port}")
        private int port;
    
        @Value("${elasticsearch.username}")
        private String userName;
    
        @Value("${elasticsearch.password}")
        private String password;
    
        @Bean(destroyMethod = "close")
        public RestHighLevelClient restClient() {
            final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            credentialsProvider.setCredentials(AuthScope.ANY,
                    new UsernamePasswordCredentials(userName, password));
    
            RestClientBuilder builder = RestClient.builder(new HttpHost(host, port))
                    .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
            return new RestHighLevelClient(builder);
    
        }
    }
               

@Configuration

用于定义配置类,指示一个类声明一个或者多个@Bean 声明的方法并且由Spring容器统一管理,以便在运行时为这些bean生成bean的定义和服务请求的类

@Bean(destroyMethod = "close")

ES RestHighLevelClient 连接的关闭方法为 close ,以便Spring容器关闭时,数据源能够正常关闭

  • Search Request

// 创建 SearchRequest
SearchRequest searchRequest = new SearchRequest(INDEX_NAME); 
// 搜索构建器   大部分搜索条件都是通过这个类来实现的
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 
searchSourceBuilder.query(QueryBuilders.matchAllQuery()); 
// 将 SearchSourceBuilder 添加到 SearchRequest
searchRequest.source(searchSourceBuilder);
           
  • SearchRequest
    • 指定查询的索引
    • 指定查询的路由分片
    • 设置IndicesOptions控制如何解决不可用的索引以及如何扩展通配符表达式
    • 指定优先去某个分片上去查询(默认的是随机先去某个分片)
  • SearchSourceBuilder
    大多数搜索行为都可以在 SearchSourceBuilder 实现,以下是一些常用的方法:
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); 
    // 查询类型 与 条件
    sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy")); 
    // 分页选项
    sourceBuilder.from(0); 
    sourceBuilder.size(5); 
    // 可设置超时时间
    sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); 
               
    构建好查询条件后,查询:
    SearchRequest searchRequest = new SearchRequest();
    searchRequest.indices("posts");
    searchRequest.source(sourceBuilder);
               
  • Search Demo

@Service
@Slf4j
public class ESService {
	// 注入 RestHighLevelClient
    private RestHighLevelClient client;
    private ObjectMapper objectMapper;

    @Autowired
    public ProfileService(RestHighLevelClient client, ObjectMapper objectMapper) {
        this.client = client;
        this.objectMapper = objectMapper;
    }

	// 通过ID查找文档
    public ProfileDocument findById(String id) throws Exception {
        GetRequest getRequest = new GetRequest(INDEX, id);
        GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
        Map<String, Object> resultMap = getResponse.getSource();
        return convertMapToProfileDocument(resultMap);
    }

	// 将es返回的数据转为java实体
    private ProfileDocument convertMapToProfileDocument(Map<String, Object> map) {
        return objectMapper.convertValue(map, ProfileDocument.class);
    }
	
	// 通过字段名查找文档
    public List<ProfileDocument> findProfileByName(String name) throws Exception {
       SearchRequest searchRequest = new SearchRequest();
       searchRequest.indices(INDEX);
       SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
       MatchQueryBuilder matchQueryBuilder = QueryBuilders
           .matchQuery("name", name)
           .operator(Operator.AND);
       searchSourceBuilder.query(matchQueryBuilder);
       searchRequest.source(searchSourceBuilder);
       SearchResponse searchResponse =
           client.search(searchRequest, RequestOptions.DEFAULT);
       return getSearchResult(searchResponse);
   }

	
    private List<ProfileDocument> getSearchResult(SearchResponse response) {
        SearchHit[] searchHit = response.getHits().getHits();
        List<ProfileDocument> profileDocuments = new ArrayList<>();
        for (SearchHit hit : searchHit) {
            profileDocuments
                .add(objectMapper
                    .convertValue(hit
                        .getSourceAsMap(), ProfileDocument.class));
        }
        return profileDocuments;
    }

}
           

继续阅读