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