欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring data elasticsearch 使用

程序员文章站 2022-07-04 23:44:38
...

很久之前就安装了elasticsearch,一直没用java用过,最近看了一下spring data系列的elasticsearch,这里写一篇心得。

如果尚未安装elasticsearch,可以 参考https://www.cnblogs.com/shaozm/p/8732842.html这篇文章。

一 、原生写法

连接客户端

先谈谈原生的写法,

 private TransportClient client;
    public TransportClient getClient(){
        Settings setting = Settings.builder()
                .put("cluster.name", "elas_cluster")
                .put("client.transport.ignore_cluster_name", true)
//                    .put("client.transport.nodes_sampler_interval", 5) //
                .put("client.transport.sniff", true)
                .build();

        client = new PreBuiltTransportClient(setting)
                .addTransportAddress(
                        new TransportAddress(new InetSocketAddress("192.168.0.2",9300))
                );
        return  client;

    }

首先连接客户端,这里单节点和集群写法一致,如果是集群的话也只需配置master节点,官方说法是客户端开启嗅探之后,会把嗅探到的节点列表把本地覆盖掉。

 

搜索

因为我是用spring data elasticsearch框架导入的数据,所以这里就不写index, type的创建,就展示一下搜索的写法。 

 public  void  search(){

        QueryBuilder queryBuilder= QueryBuilders.boolQuery()
                .must(QueryBuilders.matchQuery("newsTitle","首个电商俱乐部"))
                .must(QueryBuilders.matchQuery("newsCate","科技"));

        SearchResponse response= client.prepareSearch("test")
                .setTypes("newsArticle")
                .setQuery(queryBuilder).get();
        SearchHits searchHits = response.getHits();
        for(SearchHit searchHit : searchHits) {
            System.out.println(searchHit);
        }

        client.close();
    }

 

基本搜索解析

这里先谈一下基本的搜索

  elasticsearch 搜索请求是restful风格的,它的搜索请求都是根据 json格式的参数去搜索的。

  一般来说 elasticsearch 的普通搜索json都是类似  { "query" :  ... }     这样的,

  首先elasticsearch 的所有搜索基本分成两种,一个是 过滤 ,一种是查询 (为了区分我这里称得分搜索) ,它们区别举例说明

      像过滤搜索判断都是直接判断符不符合,比如是不是这个年龄范围的,这个字段是不是匹配的,是就返回,不是就不返回,

      而得分搜索有一个score分数作为返回依据,比如这个字段匹配的,给你一点分数,那个字段没匹配,没分数,综合所有的分数看是不是达标了,达标了返回,不达标不返回。

类似

 { "query" : {“range” : { ....... }} }

{ "query" : {“term” : { ....... }} }     term是精确查询,需要完全匹配

属于过滤搜索

{ "query" : {“match” : { ....... }} }

 { "query" : {“bool” : { ....... }} }

属于得分搜索

 而像{ "query" : {“bool” : { ....... }} } 这种是组合多个查询的,其中........ 的内容可以是多个must 或者should或者must_not或者filter的组合,最终计算score

 二、spring data elasticsearch

准备工作

现在可以进入主题了,spring data elasticsearch的用法

 先导包

 <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>3.1.2.RELEASE</version>
  </dependency>

 接着配置yml

spring:
data: elasticsearch: repositories: enabled:
true cluster-nodes: 192.168.0.2:9300 cluster-name: elas_cluster

 

异常

这里说一个bug,如果有redis你可能会抛异常,我这里是在启动类里配置了这么一行

public static void main(String[] args) throws Exception{
    System.setProperty("es.set.netty.runtime.available.processors", "false");
    SpringApplication.run(EsStart.class,args);
}

 

 

使用详解

spring-data系列的框架,用过jpa的应该都知道套路

首先配置实体注解 

@Document(indexName = "test",type = "newsArticle")
public class NewsArticlePO {
 ......
}

 


如果有什么字段需要分词器,可以单独在字段上配置
。。。。。。
@Field(type = FieldType.Text, analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
private String newsTitle;
。。。。。。

 



这时候一启动项目就会发现index,type已经自动生成了

第二步

创建repository

public interface ArticleRepository extends ElasticsearchRepository<NewsArticlePO,Long> {
   。。。。。。
}

 


这里有几种做法,一个是自己利用名字规则定义新的方法,一个是用query注解创建查询,一个是使用父类继承的方法。

第一种方法

在 ArticleRepository中创建方法
/**
* 根据标题,类别两个字段搜索
* */
List<NewsArticlePO> findByNewsTitleAndAndNewsCate(String newsTitle,String newsCate);

 

具体规则参考spring data elasticsearch的官方文档附录

第二种方法
在 ArticleRepository中创建方法 
@Query("{\"bool\": {\"must\": [{ \"match\": { \"newsTitle\": \"?0\"}},{ \"match\": { \"newsCate\": \"?1\"}}]}}")
List<NewsArticlePO> findByQuery(String newsTitle, String newsCate);

 


第三种方法
在service层代码或者其他类中注入 ArticleRepository
@Resource
private ArticleRepository articleRepository;


创建方法
public Page<NewsArticlePO> searchBuild(String newsTitle, String newsCate) {

    QueryBuilder queryBuilder= QueryBuilders.boolQuery()
            .must(QueryBuilders.matchQuery("newsTitle",newsTitle))
            .must(QueryBuilders.matchQuery("newsCate",newsCate));

    SearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(queryBuilder)
            .build();
    return   articleRepository.search(searchQuery);
}

 



这就ok了,如果不喜欢使用repository也没事,可以注入ElasticsearchTemplate
@Resource
private ElasticsearchTemplate elasticsearchTemplate;
public List<NewsArticlePO> searchTemplate(String newsTitle, String newsCate){
    QueryBuilder queryBuilder= QueryBuilders.boolQuery()
            .must(QueryBuilders.matchQuery("newsTitle",newsTitle))
            .must(QueryBuilders.matchQuery("newsCate",newsCate));

    SearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(queryBuilder)
            .build();
    return elasticsearchTemplate.queryForList(searchQuery,NewsArticlePO.class);
}

 


甚至可以通过elasticsearchTemplate.getClient()得到原生的client进行操作

demo项目地址 https://github.com/1160809039/elasticsearch-demo