SpringBoot2 集成 Spring-Data-ElasticSearch,实现相关CURD接口

项目环境:

JDK:1.8

SringBoot:2.1.0.RELEASE

Gardle:gradle-4.10.2

ElasticSearch:elasticsearch-6.2.4

Spring-data-elasticsearch:spring-data-elasticsearch:3.1.2.RELEASE

正文:

Java与ElasticSearch连接的两种方式:(1)使用Transport与ElasticSearch建立连接

                                                              (2)使用SpringDataElasticSearch连接连接

两种方式的优缺点:(1)优点:脱离框架,集成过程中不需要考虑与Spring的版本兼容问题,容易集成

                                          缺点:使用原生API操作ES,代码量大,撰写困难

                                (2)优点:将原生API进行封装,提供了ElasticsearchRepository,操作ES非常简单,与JPA同理

                                         缺点:出生于Spring家族,与SpringBoot,SpringData版本容易冲突

本章节使用Springboot+SpringDataElastic+gradle整合:

项目依赖如下:

dependencies {

    compile('org.springframework.boot:spring-boot-starter')

    // 使用SpringDataElasticSearch只需要添加一处依赖即用
    compile('org.springframework.boot:spring-boot-starter-data-elasticsearch')

    testCompile('org.springframework.boot:spring-boot-starter-test')

    // 使用lombok提供Getter与Setter,实体类只需写字段,加注释,外部类即可以通过构造器调用
    annotationProcessor 'org.projectlombok:lombok:1.18.2'
    compileOnly 'org.projectlombok:lombok:1.18.2'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.2'
    testCompileOnly 'org.projectlombok:lombok:1.18.2'

}

ElasticSearch相关配置如下(application.yml):

spring:
  data:
    elasticsearch:
      cluster-name: docker-cluster
      cluster-nodes: 127.0.0.1:9300
      repositories:
        enabled: true

 下载ElasticSearch,更改config目录下的elasticsearch.yml,找到cluster.name属性,值设置为SpringBoot配置文件中           cluster- name对应的值,并解除注释,否则项目启动失败!

  Java(实体-业务)代码如下:

  实体类pojo:

import lombok.Getter;
import lombok.Setter;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import javax.persistence.Id;
import java.io.Serializable;

@Data
@Document(indexName = "poms", type = "content")
public class ESDocument implements Serializable {

    @Id
    private String id;

    @Field(analyzer = "ik_smart", searchAnalyzer = "ik_smart")
    private String name;

    private String projectId;

}

注:实体类需要添加@Document,项目启动会在ES中自动创建index与type,需要中文分词的字段使用@Field指定分词器名称

(前提是ES服务安装了ik分词器)

关于ElasticSearch的入门知识可以参考http://blog.51cto.com/mageedu/1714522?utm_source=tuicool&utm_medium=referral

持久化dao Interface:

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;


@Repository
public interface DocumentSearchRepository extends ElasticsearchRepository<ESDocument, 
                                                                          String>   {
}

ElasticsearchRepository接口与JpaRepository同理,使用时可根据方法名称自动生成 ES Query语句,简单操作可使用该接口提供的方法(包括page,sort),简单的CRUD操作直接使用DocumentSearchRepository实例对象就可调出方法

业务service Interface:

public interface DocumentSearchService {


    ESDocument getDocumentById(String id) throws WSException;


    void deleteDocumentById(String id);


    /**
     * build add documents for the index
     *
     * @param ESDocuments added documents
     */
    void saveDocument(List<ESDocument> ESDocuments);


    /**
     * get document list by name and id order by orderField parameter
     *
     * @param name       queried name
     * @param projectId  contained project id
     * @param orderField order filed  name
     * @return document list
     * @throws GTException
     */
    List<ESDocument> getDocumentsByNameOrderByCreateOn(String name, 
                                                       String projectId,                     
                                                       String orderField) 
                                                       throws WSException;


}

业务service Implments class:

@Service
public class DocumentSearchServiceImpl implements DocumentSearchService {

    @Autowired
    private DocumentSearchRepository documentSearchRepository;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Override
    public ESDocument getDocumentById(String id) throws WSException {
        ESDocument country = documentSearchRepository.findById(id)
                                             .orElseThrow(() -> 
                                             new GTException(HttpStatus.NOT_FOUND, 
                                             ErrorCode.ES_REPOSITORY_DOCUMENT_NOT_EXISIS, 
                                             id));
        return country;
    }


    @Override
    public void deleteDocumentById(String id) {
        documentSearchRepository.deleteById(id);
    }


    /**
     * build add documents for the index
     *
     * @param ESDocuments added documents
     */
    @Override
    public void saveDocument(List<ESDocument> ESDocuments) {
        documentSearchRepository.saveAll(ESDocuments);
    }


    /**
     * get document list by name and id order by orderField parameter
     *
     * @param name       queried name
     * @param projectId  contained project id
     * @param orderField order filed  name
     * @return document list
     * @throws WSException
     */
    @Override
    public List<ESDocument> getDocumentsByNameOrderByCreateOn(String name, String 
                                 projectId, String orderField) throws WSException {
        List<ESDocument> ESDocuments;
        try {
            SearchQuery searchQuery = new NativeSearchQueryBuilder()
                    .withQuery(matchQuery("name", name))
                    .withFilter(matchPhraseQuery("projectId", projectId))
                    .withSort(SortBuilders.scoreSort().order(SortOrder.DESC))
                    .withSort(new FieldSortBuilder(orderField).order(SortOrder.DESC))
                    .build();
            ESDocuments = elasticsearchTemplate.queryForList(searchQuery, 
                                                             ESDocument.class);
        } catch (Exception e) {
            throw new WSException(HttpStatus.NOT_MODIFIED, 
                                  ErrorCode.ES_REPOSITORY_FIELD_NOT_EXISTS, e);
        }
        return ESDocuments;
    }
}

简单的查询和条件查询可以直接使用ElasticsearchRepository提供的接口,如果需要复杂的条件组合(模糊查询,完全匹配查 询,分页,排序)使用ElasticSearchTemplate实例,它一般最常用的方法是queryForList(SearchQuery query, Class<T> clazz),

将查询条件拼接到一个SearchQuery中。这个实例不需要再任何地方创建,当项目初始化的时候已经在IOC容器中创建完成了。

使用只需DI注入即可(详情可参考DocumentSearchServiceImpl类的getDocumentsByNameOrderByCreateOn方法)。

 

另外是我在整合公司项目遇到的一个坑:由于公司持久化框架也是Spring-data-Jpa,而ES使用的是Spring-data-ElasticSearch,内部使用的都是CrudRepository完成CRUD的,在整合的时候两个一直冲突,解决了三天最终项目才跑起来。强烈建议将有关ES的Interface,class与JPA的Interface,class放在不同的根目录,实体类不能引用同一个,需要创建两份实体类,ES与JPA各自用各自的,否则项目跑不起来!!!

      第一次写博客,哪里写的有问题的,欢迎大家提出宝贵的意见!谢谢!

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值