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(), "检索成功"); }