Springboot集成Elasticsearch和Xpack


1、导入依赖

  • 增加xpack功能后,必须使用xpack提供的transportClient,只能通过官网的Repo进行下载,mirrorOf设置成central
  • 开启xpack.security之后,需要配置ssl证书路径以及账号密码

pom.xml

<repositories>
        <!-- add the elasticsearch repo -->
        <repository>
            <id>elasticsearch-releases</id>
            <url>https://artifacts.elastic.co/maven</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- springboot data es -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.elasticsearch.client</groupId>
                    <artifactId>x-pack-transport</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>x-pack-transport</artifactId>
            <version>6.4.2</version>
        </dependency>
dependencies

2、Configuration配置TransportClient

注:这里必须把Elasticsearch的ssl 证书复制下来,然后进行配置

package com.owinfo.es.config;

import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import java.io.File;
import java.net.InetAddress;
/**
 * xpack client配置
 * @date 2019-07-02
 * @author pengjunjie
 */
@Configuration
public class XPackClientConfig {
	@Bean
	public TransportClient transportClient() throws Exception {
		ClassPathResource resource = new ClassPathResource("certs/elastic-certificates.p12");
		File file = resource.getFile();
		String absolutePath = file.getAbsolutePath();
		TransportClient client = new PreBuiltXPackTransportClient(Settings.builder()
				.put("cluster.name", "pms-application")
				.put("client.transport.sniff", true)
				.put("xpack.security.enabled", true)
				.put("xpack.security.transport.ssl.enabled", true)
				.put("xpack.security.transport.ssl.keystore.path", absolutePath)
				.put("xpack.security.transport.ssl.truststore.path", absolutePath)
				.put("xpack.security.transport.ssl.verification_mode","certificate")
				.put("xpack.security.user", "elastic:devops123")
				.build());
		String[] ips = new String[]{"192.168.0.16"};
		for(String ip : ips) {
			client.addTransportAddress(new TransportAddress(InetAddress.getByName(ip), 9300));
		}
		return client;
	}
}

3、实体索引设置

  • 通过settings注解,自定义分词器
  • 通过mapping注解,灵活配置映射
  • index名字,一定要是别名,防止重建索引名字被改而无法检索的问题
package com.owinfo.es.entity;

import com.owinfo.es.service.EsConstants;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.*;

/**
 * @desc Project Base Info
 * @author pjj
 * @date 2018-12-06 10:01:05
 */
@Data
@Document(indexName = EsConstants.PROJECT_INDEX, type = "project")
@Setting(settingPath = "/mapping/settings.json")
@Mapping(mappingPath = "/mapping/project.json")
public class ProjectEntity {

    /** 项目id主键 */
    @Id
    private String projectId;

    /** 数据类型、默认表名 */
    private String dataType;

    /** 项目名称 */
    private String subject;

    /** 项目类型 */
    private String projectType;

    /** 项目级别 */
    private String type;

    /** 项目编号 */
    private String projectNumber;

    /** 项目临时编号 */
    private String projectTempNumber;

    /** 所属项目群id */
    private String projectSetID;

    /** 所属项目群名称 */
    private String projectSetName;

    /** 项目状态 */
    private Integer projectState;

    /** 创建时间 */
    private String createDate;

    /** 逻辑删除 0未删除 1已删除 */
    private Integer delFlag;
}

 settings.json

{
  "index": {
    "number_of_replicas": 0,
    "number_of_shards": 1,
    "refresh_interval": "10s",
    "analysis": {
      "char_filter": {
        "word_delimit": {
          "type": "mapping",
          "mappings": [". => -"]
        }
      },
      "filter":{
        "my_pinyin":{
          "type":"pinyin",
          "first_letter":"prefix",
          "padding_char":" "
        }
      },
      "analyzer": {
        "ik_max": {
          "char_filter": ["word_delimit"],
          "tokenizer":"ik_max_word",
          "filter": ["lowercase","stemmer"]
        },
        "ik_pinyin": {
          "char_filter": "word_delimit",
          "tokenizer":"ik_max_word",
          "filter":["my_pinyin"]
        }
      }
    }
  }
}

 project.json

{
  "project" : {
    "properties" : {
      "createDate" : {
        "type" : "date",
        "format" : "yyyy-MM-dd HH:mm:ss"
      },
      "dataType" : {
        "type" : "keyword"
      },
      "delFlag" : {
        "type" : "integer"
      },
      "projectId" : {
        "type" : "keyword"
      },
      "projectNumber" : {
        "type" : "keyword"
      },
      "projectSetID" : {
        "type" : "keyword"
      },
      "projectSetName" : {
        "type" : "keyword"
      },
      "projectState" : {
        "type" : "integer"
      },
      "projectTempNumber" : {
        "type" : "keyword"
      },
      "projectType" : {
        "type" : "keyword"
      },
      "subject" : {
        "type" : "text",
        "analyzer" : "ik_max"
      },
      "type" : {
        "type" : "keyword"
      }
    }
  }
}

4、Repository持久化操作

package com.owinfo.es.repository;

import com.owinfo.es.entity.ProjectEntity;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ProjectRepo extends ElasticsearchRepository<ProjectEntity, String> {
}

 

5、通用查询方法

SearchCommonDto.java
/**
 * @desc 公共方法查询条件
 * @author pjj
 * @date 2018-12-11 09:51:48
 */
@Getter
@Setter
public class SearchCommonDto {

    public SearchCommonDto() {
        this.preTag = "<red>";
        this.postTag = "</red>";
    }

    public SearchCommonDto(String preTag, String postTag) {
        this.preTag = preTag;
        this.postTag = postTag;
    }

    private String[] indices;
    private String[] highlightFields;
    private String[] sortFields;
    private Integer page;
    private Integer pageSize;
    private QueryBuilder queryBuilder;
    private String[] excludes;
    private String preTag;
    private String postTag;
}

通用查询方法,可以进行高亮排序,scroll查询等等

   /**
     * 根据SearchResponse获取高亮后的查询结果
     * @param response
     * @return
     */
    public List<Map<String, Object>> getSearchResponse(SearchResponse response) {
        List<Map<String, Object>> source = new ArrayList<>();
        for (SearchHit searchHit: response.getHits()) {
            Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
            Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
            highlightFields.entrySet().forEach(highlightKey -> {
                StringBuilder stringBuilder = new StringBuilder();
                Text[] texts = highlightKey.getValue().getFragments();
                for (Text text: texts) {
                    stringBuilder.append(text.string());
                }
                sourceAsMap.put(highlightKey.getKey(), stringBuilder);
            });
            source.add(sourceAsMap);
        }
        return source;
    }

    /**
     * 统一查询、普通查询、深度分页查询
     * @param searchDto
     * @return
     */
    public JSONObject searchCommon(SearchCommonDto searchDto) {
        SearchRequestBuilder requestBuilder = template.getClient().prepareSearch(searchDto.getIndices());

        //去除_source字段
        String[] excludes = searchDto.getExcludes();
        if (excludes != null && excludes.length > 0) {
            requestBuilder.setFetchSource(null, excludes);
        }

        // 先按评分排序
        String[] sortFields = searchDto.getSortFields();
        if (sortFields != null && sortFields.length > 0) {
            for (int i = 0; i < sortFields.length; i++) {
                requestBuilder.addSort(sortFields[i], SortOrder.DESC);
            }
        }

        //高亮
        String[] highlightFields = searchDto.getHighlightFields();
        if (highlightFields != null && highlightFields.length > 0) {
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.preTags(searchDto.getPreTag());
            highlightBuilder.postTags(searchDto.getPostTag());
            for (int i = 0; i < highlightFields.length; i++) {
                HighlightBuilder.Field field = new HighlightBuilder.Field(highlightFields[i]);
                highlightBuilder.field(field);
            }
            requestBuilder.highlighter(highlightBuilder);
        }

        //设置QueryBuilder
        if (searchDto.getQueryBuilder() != null) {
            requestBuilder.setQuery(searchDto.getQueryBuilder());
        }

        SearchResponse searchResponse = null;
        /** 0-10000条使用普通查询 */
        if (searchDto.getPageSize() * searchDto.getPage() <= EsConstants.DEEP_PAGING_NUM) {
            requestBuilder.setFrom((searchDto.getPage() -1) * searchDto.getPageSize());
            requestBuilder.setSize(searchDto.getPageSize());
            searchResponse = requestBuilder.execute().actionGet();
        } else {
            /** deep paging scroll查询 保存30秒, 10000以后使用 scroll查询*/
            searchResponse = requestBuilder.setSize(searchDto.getPageSize())
                    .setScroll(TimeValue.timeValueSeconds(30))
                    .execute().actionGet();

            int currentPage = 1;
            while (searchResponse.getHits().getHits().length >  0 && currentPage < searchDto.getPage()) {
                currentPage++;
                searchResponse = template.getClient().prepareSearchScroll(searchResponse.getScrollId())
                        .setScroll(TimeValue.timeValueSeconds(30))
                        .execute().actionGet();
            }

            ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
            clearScrollRequest.addScrollId(searchResponse.getScrollId());
            template.getClient().clearScroll(clearScrollRequest);
            log.info("==> deep paging scroll查询成功");
        }

        long total = searchResponse.getHits().totalHits;
        List<Map<String, Object>> source = getSearchResponse(searchResponse);
        return ApiResult.PAGE(source, total, searchDto.getPage(), searchDto.getPageSize(), "检索成功");
    }

  


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM