概述
直接忽略安装教程,网上一搜一大把,安装起来也比较简单。但是网上对于Java RestClient 能够集成很好的没有。接下来我将根据官方API集成了一套Java RestClient API操作模板。
环境说明:
SpringBoot2.1.3 + JDK1.8 + Maven(Springboot自带不好使用,建议按照自己的方式封装)
需要源代码的可以加我微信[JornTang]
application.yml
elasticsearch:
# ip地址,多个使用,分隔
ipAddrs: 127.0.0.1:9200,127.0.0.1:9201
client:
# 连接目标url最大超时
connectTimeOut: 5000
# 等待响应(读数据)最大超时
socketTimeOut: 6000
# 从连接池中获取可用连接最大超时时间
connectionRequestTime: 3000
# 连接池中的最大连接数
maxConnectNum: 30
# 连接同一个route最大的并发数
maxConnectPerRoute: 10
pom.xml
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.0.1</version>
</dependency>
直接上代码。【ps: 代码待重构】
1、创建RestClientConfig配置类
/**
* elasticsearch 配置
*/
@Configuration
public class RestClientConfig {
/**
* elasticsearch 连接地址多个地址使用,分隔
*/
@Value("${elasticsearch.ipAddrs}")
private String[] ipAddrs;
/**
* 连接目标url最大超时
*/
@Value("${elasticsearch.client.connectTimeOut}")
private Integer connectTimeOut;
/**
* 等待响应(读数据)最大超时
*/
@Value("${elasticsearch.client.socketTimeOut}")
private Integer socketTimeOut;
/**
* 从连接池中获取可用连接最大超时时间
*/
@Value("${elasticsearch.client.connectionRequestTime}")
private Integer connectionRequestTime;
/**
* 连接池中的最大连接数
*/
@Value("${elasticsearch.client.maxConnectNum}")
private Integer maxConnectNum;
/**
* 连接同一个route最大的并发数
*/
@Value("${elasticsearch.client.maxConnectPerRoute}")
private Integer maxConnectPerRoute;
@Bean
public HttpHost[] httpHost(){
HttpHost[] httpHosts = new HttpHost[ipAddrs.length];
for (int i = 0; i < ipAddrs.length; i++) {
String[] ipAddr = ipAddrs[i].split(":");
httpHosts[i] = new HttpHost(ipAddr[0], Integer.valueOf(ipAddr[1]), "http");
}
return httpHosts;
}
@Bean(initMethod="init",destroyMethod="close")
public ElasticRestClientFactory getFactory(){
return ElasticRestClientFactory.
build(httpHost(), connectTimeOut, socketTimeOut, connectionRequestTime, maxConnectNum, maxConnectPerRoute);
}
@Bean
@Scope("singleton")
public RestClient getRestClient(){
return getFactory().getClient();
}
@Bean
@Scope("singleton")
public RestHighLevelClient getRestHighClient(){
return getFactory().getRestHighClient();
}
}
2、创建ElasticRestClientFactory工厂类
public class ElasticRestClientFactory {
private static Logger log = LoggerFactory.getLogger(ElasticRestClientFactory.class);
// 连接目标url最大超时
public static int CONNECT_TIMEOUT_MILLIS = 3000;
// 等待响应(读数据)最大超时
public static int SOCKET_TIMEOUT_MILLIS = 6000;
// 从连接池中获取可用连接最大超时时间
public static int CONNECTION_REQUEST_TIMEOUT_MILLIS = 2000;
// 连接池中的最大连接数
public static int MAX_CONN_TOTAL =15;
// 连接同一个route最大的并发数
public static int MAX_CONN_PER_ROUTE = 10;
private static HttpHost[] HTTP_HOST;
private RestClientBuilder builder;
private RestClient restClient;
private RestHighLevelClient restHighLevelClient;
private static ElasticRestClientFactory restClientFactory = new ElasticRestClientFactory();
private ElasticRestClientFactory(){}
public static ElasticRestClientFactory build(HttpHost[] httpHost, Integer maxConnectNum, Integer maxConnectPerRoute){
HTTP_HOST = httpHost;
MAX_CONN_TOTAL = maxConnectNum;
MAX_CONN_PER_ROUTE = maxConnectPerRoute;
return restClientFactory;
}
public static ElasticRestClientFactory build(HttpHost[] httpHost,Integer connectTimeOut, Integer socketTimeOut,
Integer connectionRequestTime,Integer maxConnectNum, Integer maxConnectPerRoute){
HTTP_HOST = httpHost;
CONNECT_TIMEOUT_MILLIS = connectTimeOut;
SOCKET_TIMEOUT_MILLIS = socketTimeOut;
CONNECTION_REQUEST_TIMEOUT_MILLIS = connectionRequestTime;
MAX_CONN_TOTAL = maxConnectNum;
MAX_CONN_PER_ROUTE = maxConnectPerRoute;
return restClientFactory;
}
public void init(){
builder = RestClient.builder(HTTP_HOST);
setConnectTimeOutConfig();
setMutiConnectConfig();
restClient = builder.build();
restHighLevelClient = new RestHighLevelClient(builder);
log.info("Elasticsearch highLevelRestClient init successful");
}
// 配置连接延时时间
public void setConnectTimeOutConfig(){
builder.setRequestConfigCallback(requestConfigBuilder -> {
requestConfigBuilder.setConnectTimeout(CONNECT_TIMEOUT_MILLIS);
requestConfigBuilder.setSocketTimeout(SOCKET_TIMEOUT_MILLIS);
requestConfigBuilder.setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT_MILLIS);
return requestConfigBuilder;
});
}
// 使用异步httpclient时设置并发连接数
public void setMutiConnectConfig(){
builder.setHttpClientConfigCallback(httpClientBuilder -> {
httpClientBuilder.setMaxConnTotal(MAX_CONN_TOTAL);
httpClientBuilder.setMaxConnPerRoute(MAX_CONN_PER_ROUTE);
return httpClientBuilder;
});
}
public RestClient getClient(){
return restClient;
}
public RestHighLevelClient getRestHighClient(){
return restHighLevelClient;
}
public void close() {
if (restClient != null) {
try {
restClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
log.info("Elasticsearch highLevelRestClient closed");
}
}
3、创建QueryResult查询结果封装类
public class QueryResult {
/**
* 查询是否成功true=成功,false=失败
*/
private boolean succesful;
/**
* 查询耗时
*/
private long took;
/**
* 是否超时
*/
private boolean timedout;
/**
* 查询总数
*/
private long hitsTotal;
/**
* 最高评分
*/
private float maxScore;
/**
* 分片信息
* total : 分片总数
* successful : 成功查询的分片数
* skipped" : 跳过查询的分片数
* failed" : 失败查询的分片数
*/
private Map<String,Integer> shardsInfo;
/**
* 查询结果
*/
private List<Map<String,Object>> hitsBody;
public QueryResult() {
}
public QueryResult(boolean succesful) {
this.succesful = succesful;
}
public boolean getSuccesful() {
return succesful;
}
public void setSuccesful(boolean succesful) {
this.succesful = succesful;
}
public long getTook() {
return took;
}
public void setTook(long took) {
this.took = took;
}
public boolean isTimedout() {
return timedout;
}
public void setTimedout(boolean timedout) {
this.timedout = timedout;
}
public long getHitsTotal() {
return hitsTotal;
}
public void setHitsTotal(long hitsTotal) {
this.hitsTotal = hitsTotal;
}
public float getMaxScore() {
return maxScore;
}
public void setMaxScore(float maxScore) {
this.maxScore = maxScore;
}
public Map<String, Integer> getShardsInfo() {
return shardsInfo;
}
public void setShardsInfo(Map<String, Integer> shardsInfo) {
this.shardsInfo = shardsInfo;
}
public List<Map<String, Object>> getHitsBody() {
return hitsBody;
}
public void setHitsBody(List<Map<String, Object>> hitsBody) {
this.hitsBody = hitsBody;
}
}
4、创建ElasticQueryDSLTemplates模板类【基于Query DSL】后续会增加基于SQL一套模板方法
/**
* elasticsearch restClient 工具类
* @author dell
* 更多API请参考官网https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html
*/
@Component
public class ElasticQueryDSLTemplates {
private static Logger log = LoggerFactory.getLogger(ElasticQueryDSLTemplates.class);
@Autowired
private RestHighLevelClient restHighLevelClient;
/**######################################## Index API #################################################
* https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-supported-apis.html
*
*/
/**
* 创建索引
* @param indexName
* @param builder
* @return
* @throws IOException
*/
public boolean createIndex(String indexName, Builder builder) throws IOException {
Assert.notNull(indexName, "索引名称不能为空");
CreateIndexRequest request = new CreateIndexRequest(indexName);
request.settings(Settings.builder()
.put("index.number_of_shards", 3) // 分片
.put("index.number_of_replicas", 1) //副本
.put("refresh_interval", "10s")
);
// 创建fullText属性
Map<String, Object> fullText = new HashMap<>();
fullText.put("type", "text");
fullText.put("analyzer", "ik_max_word"); // 可选ik_max_word、ik_smart
fullText.put("search_analyzer", "ik_smart"); // 可选ik_max_word、ik_smart
fullText.put("term_vector", "with_positions_offsets"); // 全文检索fvh设置
// 创建fondCode属性
Map<String, Object> fondCode = new HashMap<>();
fondCode.put("type", "keyword");
Map<String, Object> properties = new HashMap<>();
properties.put("fullText", fullText);
properties.put("fondCode", fondCode);
Map<String, Object> mapping = new HashMap<>();
mapping.put("properties", properties);
request.mapping(mapping);
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
boolean acknowledged = createIndexResponse.isAcknowledged();
return acknowledged;
}
/**
* 删除索引
* @param indexName 索引名称
* @return
* @throws IOException
*/
public boolean deleteIndex(String indexName) throws IOException {
Assert.notNull(indexName, "索引名称不能为空");
DeleteIndexRequest request = new DeleteIndexRequest(indexName);
AcknowledgedResponse deleteIndexResponse = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
return deleteIndexResponse.isAcknowledged();
}
/**
* 判断索引是否存在
* @param indexName 索引名称
* @return
* @throws IOException
*/
public boolean existsIndex(String indexName) throws IOException {
Assert.notNull(indexName, "索引名称不能为空");
GetIndexRequest request = new GetIndexRequest(indexName);
return restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
}
/**
* 文本分析
* @param analyzer 分析器
* @param analyzeText 分析文本
* @return
* @throws IOException
*/
public List<AnalyzeResponse.AnalyzeToken> analyzeText(String analyzer, String analyzeText) throws IOException {
Assert.notNull(analyzer, "分析器不能为空");
Assert.notNull(analyzeText, "分析文本不能为空");
AnalyzeRequest analyzeRequest = new AnalyzeRequest();
analyzeRequest.analyzer(analyzer);
analyzeRequest.text(analyzeText);
AnalyzeResponse response = restHighLevelClient.indices().analyze(analyzeRequest, RequestOptions.DEFAULT);
return response.getTokens();
}
/**######################################## Index Document API #################################################
* https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-supported-apis.html
*
*/
/**
* 添加索引文档
* @param indexName 索引名称
* @param id 文档id
* @param docMap 文档map
* @return
* @throws IOException
*/
public boolean addDocument(String indexName, String id, Map<String, Object> docMap) {
boolean optFlag = Boolean.TRUE;
try {
Assert.notNull(indexName, "索引名称不能为空");
Assert.notNull(id, "索引文档ID不能为空");
Assert.notNull(docMap, "索引文档docMap不能为空");
IndexRequest indexRequest = new IndexRequest(indexName).id(id).source(docMap);
indexRequest.opType(DocWriteRequest.OpType.CREATE);
restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("添加索引文档失败异常。索引名称【{}】,索引文档ID【{}】", indexName, id, e);
optFlag = Boolean.FALSE;
}
return optFlag;
}
/**
* 根据ID获取索引文档
* @param indexName 索引名称
* @param id 文档id
* @return
* @throws IOException
*/
public Map<String, Object> getDocument(String indexName, String id) {
Map<String, Object> docMap = null;
try {
Assert.notNull(indexName, "索引名称不能为空");
Assert.notNull(id, "索引文档ID不能为空");
GetRequest request = new GetRequest(indexName, id);
GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
docMap = response.getSourceAsMap();
} catch (Exception e) {
log.error("根据ID获取索引文档异常。索引名称【{}】,索引文档ID【{}】", indexName, id, e);
}
return docMap;
}
/**
* 根据ID判断索引文档是否存在
* @param indexName 索引名称
* @param id 文档id
* @return
* @throws IOException
*/
public boolean existsDocument(String indexName, String id) {
boolean optFlag = Boolean.TRUE;
try {
Assert.notNull(indexName, "索引名称不能为空");
Assert.notNull(id, "索引文档ID不能为空");
GetRequest request = new GetRequest(indexName, id);
request.fetchSourceContext(new FetchSourceContext(false));
request.storedFields("_none_");
optFlag = restHighLevelClient.exists(request, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("根据ID判断索引文档是否存在异常。索引名称【{}】,索引文档ID【{}】", indexName, id, e);
}
return optFlag;
}
/**
* 根据ID删除索引文档
* @param indexName 索引名称
* @param id 文档id
* @return
* @throws IOException
*/
public boolean deleteDocument(String indexName, String id) {
boolean optFlag = Boolean.TRUE;
try {
Assert.notNull(indexName, "索引名称不能为空");
Assert.notNull(id, "索引文档ID不能为空");
GetRequest request = new GetRequest(indexName, id);
request.fetchSourceContext(new FetchSourceContext(false));
request.storedFields("_none_");
optFlag = restHighLevelClient.exists(request, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("根据ID删除索引文档异常。索引名称【{}】,索引文档ID【{}】", indexName, id, e);
}
return optFlag;
}
/**
* 根据ID修改索引文档
* @param indexName 索引名称
* @param id 文档id
* @param docMap 文档map
* @return
* @throws IOException
*/
public boolean updateDocument(String indexName, String id, Map<String, Object> docMap) {
boolean optFlag = Boolean.TRUE;
try {
Assert.notNull(indexName, "索引名称不能为空");
Assert.notNull(id, "索引文档ID不能为空");
Assert.notNull(docMap, "索引文档docMap不能为空");
UpdateRequest request = new UpdateRequest(indexName, id).doc(docMap);
restHighLevelClient.update(request, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("根据ID修改索引文档异常。索引名称【{}】,索引文档ID【{}】", indexName, id, e);
}
return optFlag;
}
/**
* 批量添加索引文档
* @param indexName 索引名称
* @param docMaps 文档maps
* @return
* @throws IOException
*/
public boolean bulkAddDocument(String indexName, List<Map<String, Object>> docMaps) {
boolean optFlag = Boolean.TRUE;
try {
Assert.notNull(indexName, "索引名称不能为空");
Assert.notNull(docMaps, "索引文档docMaps不能为空");
BulkRequest bulkRequest = new BulkRequest();
for (int i = 0; i < docMaps.size(); i++) {
Map<String, Object> docMap = docMaps.get(i);
bulkRequest.add(new IndexRequest(indexName).id(docMap.get("id")+"").source(docMaps).opType(DocWriteRequest.OpType.CREATE));
}
restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("批量添加索引文档异常。索引名称【{}】", indexName, e);
}
return optFlag;
}
/**
* 批量修改索引文档
* @param indexName 索引名称
* @param docMaps 文档maps
* @return
* @throws IOException
*/
public boolean bulkUpdateDocument(String indexName, List<Map<String, Object>> docMaps) {
boolean optFlag = Boolean.TRUE;
try {
Assert.notNull(indexName, "索引名称不能为空");
Assert.notNull(docMaps, "索引文档docMaps不能为空");
BulkRequest bulkRequest = new BulkRequest();
for (int i = 0; i < docMaps.size(); i++) {
Map<String, Object> docMap = docMaps.get(i);
bulkRequest.add(new UpdateRequest(indexName, docMap.get("id")+"").doc(docMap));
}
restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("批量修改索引文档异常。索引名称【{}】", indexName, e);
}
return optFlag;
}
/**
* 批量修改索引文档
* @param indexName 索引名称
* @param docMaps 文档maps
* @return
* @throws IOException
*/
public boolean bulkDeleteDocument(String indexName, List<Map<String, Object>> docMaps) {
boolean optFlag = Boolean.TRUE;
try {
Assert.notNull(indexName, "索引名称不能为空");
Assert.notNull(docMaps, "索引文档docMaps不能为空");
BulkRequest bulkRequest = new BulkRequest();
for (int i = 0; i < docMaps.size(); i++) {
Map<String, Object> docMap = docMaps.get(i);
bulkRequest.add(new DeleteRequest(indexName, docMap.get("id")+""));
}
restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
log.error("批量修改索引文档异常。索引名称【{}】", indexName, e);
}
return optFlag;
}
/**######################################## QUERY DSL #################################################
* https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-match-all-query.html
*
*/
/**
* 精准匹配--检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param terms 匹配条件
* @return SQL翻译 select * from xxx_table where fieldName in(term1,term2)
* GET /_search
* {
* "query": {
* "terms" : { "user" : ["kimchy", "elasticsearch"]}
* }
* }
* @throws IOException
*/
public QueryResult searchForTermsQuery(String indexName, String fieldName, Object... terms ) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
Assert.notNull(terms, "精准查询条件terms不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.termsQuery(fieldName, terms));
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error("精准匹配检索异常。索引名称【{}】, terms查询字段【{}】,查询条件【{}】", indexName, fieldName, JSONObject.toJSONString(terms), e);
}
return qr;
}
/**
* 精准匹配--分页检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param terms 匹配条件
* @return SQL翻译 select * from xxx_table where fieldName in(term1,term2)
* GET /_search
* {
* "query": {
* "terms" : { "user" : ["kimchy", "elasticsearch"]}
* }
* }
* @throws IOException
*/
public QueryResult searchForTermsQuery(String indexName, String fieldName, int offset, int pageSize, Object... terms ) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
Assert.notNull(terms, "精准查询条件terms不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.termsQuery(fieldName, terms));
// 设置分页
sourceBuilder.from(offset).size(pageSize);
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error("精准匹配分页检索异常。索引名称【{}】, terms查询字段【{}】,查询条件【{}】", indexName, fieldName, JSONObject.toJSONString(terms), e);
}
return qr;
}
/**
* 范围匹配--检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param range 支持 gte(>=)、gt(>)、lte(<=)、lt(<)
* @return SQL翻译 select * from xxx_table where age >=18 and age<20
* GET _search
* {
* "query": {
* "range" : {
* "age" : {
* "gte" : 10,
* "lte" : 20,
* "boost" : 2.0
* }
* }
* }
* }
* @throws IOException
*/
public QueryResult searchForRangeQuery(String indexName, String fieldName, Map<String, Object> terms, String format) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
Assert.notNull(terms, "范围查询条件terms不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 设置range查询条件
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(fieldName);
for (String key: terms.keySet()) {
switch (key) {
case "gte":
rangeQueryBuilder.gte(terms.get(key));
continue;
case "gt":
rangeQueryBuilder.gt(terms.get(key));
continue;
case "lte":
rangeQueryBuilder.lte(terms.get(key));
continue;
case "lt":
rangeQueryBuilder.lt(terms.get(key));
continue;
default:
break;
}
}
// 设置转换规则 一般针对时间属性 dd/MM/yyyy||yyyy
if(StringUtils.isNotEmpty(format)) {
rangeQueryBuilder.format(format);
}
sourceBuilder.query(rangeQueryBuilder);
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error("单属性范围匹配检索异常。索引名称【{}】, range查询字段【{}】,查询条件【{}】", indexName, fieldName, JSONObject.toJSONString(terms), e);
}
return qr;
}
/**
* 范围匹配-分页检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param range 支持 gte(>=)、gt(>)、lte(<=)、lt(<)
* @return SQL翻译 select * from xxx_table where age >=18 and age<20
* GET _search
* {
* "query": {
* "range" : {
* "age" : {
* "gte" : 10,
* "lte" : 20,
* "boost" : 2.0
* }
* }
* }
* }
* @throws IOException
*/
public QueryResult searchForRangeQuery(String indexName, String fieldName, int offset, int pageSize, Map<String, Object> terms, String format) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
Assert.notNull(terms, "范围查询条件terms不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 设置range查询条件
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(fieldName);
for (String key: terms.keySet()) {
switch (key) {
case "gte":
rangeQueryBuilder.gte(terms.get(key));
continue;
case "gt":
rangeQueryBuilder.gt(terms.get(key));
continue;
case "lte":
rangeQueryBuilder.lte(terms.get(key));
continue;
case "lt":
rangeQueryBuilder.lt(terms.get(key));
continue;
default:
break;
}
}
// 设置转换规则 一般针对时间属性 dd/MM/yyyy||yyyy
if(StringUtils.isNotEmpty(format)) {
rangeQueryBuilder.format(format);
}
sourceBuilder.query(rangeQueryBuilder);
// 设置分页
sourceBuilder.from(offset).size(pageSize);
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error("单属性范围匹配分页检索异常。索引名称【{}】, range查询字段【{}】,查询条件【{}】", indexName, fieldName, JSONObject.toJSONString(terms), e);
}
return qr;
}
/**
* 前缀模糊匹配--检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param term 匹配条件
* @return SQL翻译 select * from xxx_table where fieldName like 'prefix%'
* GET /_search
* { "query": {
* "prefix" : { "user" : "ki" }
* }
* }
* @throws IOException
*/
public QueryResult searchForPrefixQuery(String indexName, String fieldName, String term) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
Assert.notNull(term, "前缀模糊检索条件term不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.prefixQuery(fieldName, term));
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error(" 前缀模糊匹配检索异常。索引名称【{}】, terms查询字段【{}】,查询条件【{}】", indexName, fieldName, term, e);
}
return qr;
}
/**
* 前缀模糊匹配--分页检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param terms 匹配条件
* @return SQL翻译 select * from xxx_table where fieldName like 'prefix%'
* GET /_search
* { "query": {
* "prefix" : { "user" : "ki" }
* }
* }
* @throws IOException
*/
public QueryResult searchForPrefixQuery(String indexName, String fieldName, int offset, int pageSize, String term ) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
Assert.notNull(term, "前缀模糊检索条件term不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.prefixQuery(fieldName, term));
//设置分页
sourceBuilder.from(offset).size(pageSize);
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error(" 前缀模糊匹配分页检索异常。索引名称【{}】, terms查询字段【{}】,查询条件【{}】", indexName, fieldName, term, e);
}
return qr;
}
/**
* 通配符模糊匹配--检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param term 匹配条件
* @return SQL翻译 select * from xxx_table where fieldName like 'xxx%xxx'
* GET /_search
* {
* "query": {
* "wildcard" : { "user" : "ki*y" }
* }
* }
* @throws IOException
*/
public QueryResult searchForWildcardQuery(String indexName, String fieldName, String term) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
Assert.notNull(term, "通配符模糊检索条件term不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.wildcardQuery(fieldName, term));
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error(" 通配符模糊匹配检索异常。索引名称【{}】, term查询字段【{}】,查询条件【{}】", indexName, fieldName, term, e);
}
return qr;
}
/**
* 通配符模糊匹配--分页检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param terms 匹配条件
* @return SQL翻译 select * from xxx_table where fieldName like 'xxx%xxx'
* GET /_search
* {
* "query": {
* "wildcard" : { "user" : "ki*y" }
* }
* }
* @throws IOException
*/
public QueryResult searchForWildcardQuery(String indexName, String fieldName, int offset, int pageSize, String term ) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
Assert.notNull(term, "通配符模糊检索条件term不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.wildcardQuery(fieldName, term));
// 设置分页
sourceBuilder.from(offset).size(pageSize);
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error(" 通配符模糊匹配检索异常。索引名称【{}】, term查询字段【{}】,查询条件【{}】", indexName, fieldName, term, e);
}
return qr;
}
/**
* 模糊匹配--检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param terms 匹配条件
* @return SQL翻译 select * from xxx_table where fieldName like '%term%'
* GET /_search
* {
* "query": {
* "fuzzy" : { "user" : "ki" }
* }
* }
* @throws IOException
*/
public QueryResult searchForFuzzyQuery(String indexName, String fieldName, Object term) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
Assert.notNull(term, "模糊检索条件term不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.fuzzyQuery(fieldName, term));
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error(" 模糊匹配检索异常。索引名称【{}】, term查询字段【{}】,查询条件【{}】", indexName, fieldName, term, e);
}
return qr;
}
/**
* 模糊匹配--分页检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param terms 匹配条件
* @return SQL翻译 select * from xxx_table where fieldName like '%term%'
* GET /_search
* {
* "query": {
* "fuzzy" : { "user" : "ki" }
* }
* }
* @throws IOException
*/
public QueryResult searchForFuzzyQuery(String indexName, String fieldName, int offset, int pageSize, Object term ) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
Assert.notNull(term, "模糊检索条件term不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.fuzzyQuery(fieldName, term));
// 设置分页
sourceBuilder.from(offset).size(pageSize);
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error("模糊匹配检索异常。索引名称【{}】, term查询字段【{}】,查询条件【{}】", indexName, fieldName, term, e);
}
return qr;
}
/**
* 根据ids匹配--检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param terms 匹配条件
* @return SQL翻译 select * from xxx_table where id in(id1,id2...)
* GET /_search
* {
* "query": {
* "ids" : {
* "values" : ["1", "2", "3"]
* }
* }
* }
* @throws IOException
*/
public QueryResult searchForIdsQuery(String indexName, String fieldName, String... terms ) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
Assert.notNull(terms, "ids检索条件term不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.idsQuery(terms));
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error("根据ids匹配检索异常。索引名称【{}】, term查询字段【{}】,查询条件【{}】", indexName, fieldName, JSONObject.toJSONString(terms), e);
}
return qr;
}
/**
* 根据ids匹配--分页检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param terms 匹配条件
* @return SQL翻译 select * from xxx_table where id in(id1,id2...)
* GET /_search
* {
* "query": {
* "ids" : {
* "values" : ["1", "2", "3"]
* }
* }
* }
* @throws IOException
*/
public QueryResult searchForIdsQuery(String indexName, String fieldName, int offset, int pageSize, String... terms ) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
Assert.notNull(terms, "ids检索条件term不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.idsQuery(terms));
// 设置分页
sourceBuilder.from(offset).size(pageSize);
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error("根据ids匹配分页检索异常。索引名称【{}】, term查询字段【{}】,查询条件【{}】", indexName, fieldName, JSONObject.toJSONString(terms), e);
}
return qr;
}
/**######################################## QUERY DSL【复合查询】 #################################################
* https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-match-all-query.html
*
*/
/**
* 复合匹配--检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param bool 支持
* must 必须出现在匹配的文档中,并有助于得分
* filter 必须出现在匹配的文档中。但是不同于 must查询的分数将被忽略。过滤器子句在过滤器上下文中执行,这意味着忽略评分并考虑使用子句进行高速缓存
* should 应出现在匹配的文档中
* must_not不得出现在匹配的文档中
* @return SQL翻译 select * from xxx_table where age >=18 and age<20 and name not in(name1,name2)
* POST _search
* {
* "query": {
* "bool" : {
* "must" : {
* "term" : { "user" : "kimchy" }
* },
* "filter": {
* "term" : { "tag" : "tech" }
* },
* "must_not" : {
* "range" : {
* "age" : { "gte" : 10, "lte" : 20 }
* }
* },
* "should" : [
* { "term" : { "tag" : "wow" } },
* { "term" : { "tag" : "elasticsearch" } }
* ],
* "minimum_should_match" : 1,
* "boost" : 1.0
* }
* }
* }
* @throws IOException
*/
public QueryResult searchForBoolQuery(String indexName, Map<String, List<QueryBuilder>> terms) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
//Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
//Assert.notNull(terms, "范围查询条件terms不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 设置复合查询
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
for (String key: terms.keySet()) {
switch (key) {
case "must":
List<QueryBuilder> mustQbs = terms.get(key);
for(QueryBuilder qb: mustQbs) {
boolQueryBuilder.must(qb);
}
continue;
case "filter":
List<QueryBuilder> filterQbs = terms.get(key);
for(QueryBuilder qb: filterQbs) {
boolQueryBuilder.filter(qb);
}
continue;
case "mustNot":
List<QueryBuilder> mustNotQbs = terms.get(key);
for(QueryBuilder qb: mustNotQbs) {
boolQueryBuilder.mustNot(qb);
}
continue;
case "should":
List<QueryBuilder> shouldQbs = terms.get(key);
for(QueryBuilder qb: shouldQbs) {
boolQueryBuilder.should(qb);
}
continue;
default:
break;
}
}
sourceBuilder.query(boolQueryBuilder);
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error("复合匹配检索异常。索引名称【{}】", indexName, e);
}
return qr;
}
/**
* 复合匹配--分页检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param bool 支持
* must 必须出现在匹配的文档中,并有助于得分
* filter 必须出现在匹配的文档中。但是不同于 must查询的分数将被忽略。过滤器子句在过滤器上下文中执行,这意味着忽略评分并考虑使用子句进行高速缓存
* should 应出现在匹配的文档中
* must_not不得出现在匹配的文档中
* @return SQL翻译 select * from xxx_table where age >=18 and age<20 and name not in(name1,name2)
* POST _search
* {
* "query": {
* "bool" : {
* "must" : {
* "term" : { "user" : "kimchy" }
* },
* "filter": {
* "term" : { "tag" : "tech" }
* },
* "must_not" : {
* "range" : {
* "age" : { "gte" : 10, "lte" : 20 }
* }
* },
* "should" : [
* { "term" : { "tag" : "wow" } },
* { "term" : { "tag" : "elasticsearch" } }
* ],
* "minimum_should_match" : 1,
* "boost" : 1.0
* }
* }
* }
* @throws IOException
*/
public QueryResult searchForBoolQuery(String indexName, int offset, int pageSize, Map<String, List<QueryBuilder>> terms) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
//Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
//Assert.notNull(terms, "范围查询条件terms不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 设置复合查询
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
for (String key: terms.keySet()) {
switch (key) {
case "must":
List<QueryBuilder> mustQbs = terms.get(key);
for(QueryBuilder qb: mustQbs) {
boolQueryBuilder.must(qb);
}
continue;
case "filter":
List<QueryBuilder> filterQbs = terms.get(key);
for(QueryBuilder qb: filterQbs) {
boolQueryBuilder.filter(qb);
}
continue;
case "mustNot":
List<QueryBuilder> mustNotQbs = terms.get(key);
for(QueryBuilder qb: mustNotQbs) {
boolQueryBuilder.mustNot(qb);
}
continue;
case "should":
List<QueryBuilder> shouldQbs = terms.get(key);
for(QueryBuilder qb: shouldQbs) {
boolQueryBuilder.should(qb);
}
continue;
default:
break;
}
}
sourceBuilder.query(boolQueryBuilder);
// 设置分页
sourceBuilder.from(offset).size(pageSize);
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error("复合匹配分页检索异常。索引名称【{}】", indexName, e);
}
return qr;
}
/**######################################## QUERY DSL【高亮查询】 #################################################
* https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-search.html
*
*/
/**
* 复合匹配--高亮检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param bool 支持
* must 必须出现在匹配的文档中,并有助于得分
* filter 必须出现在匹配的文档中。但是不同于 must查询的分数将被忽略。过滤器子句在过滤器上下文中执行,这意味着忽略评分并考虑使用子句进行高速缓存
* should 应出现在匹配的文档中
* must_not不得出现在匹配的文档中
* @return SQL翻译 select * from xxx_table where age >=18 and age<20 and name not in(name1,name2)
* POST _search
* {
* "query": {
* "bool" : {
* "must" : {
* "term" : { "user" : "kimchy" }
* },
* "filter": {
* "term" : { "tag" : "tech" }
* },
* "must_not" : {
* "range" : {
* "age" : { "gte" : 10, "lte" : 20 }
* }
* },
* "should" : [
* { "term" : { "tag" : "wow" } },
* { "term" : { "tag" : "elasticsearch" } }
* ],
* "minimum_should_match" : 1,
* "boost" : 1.0
* }
* },
* "highlight": {
* "pre_tags": "<em>",
* "post_tags": "</em>",
* "fields": {
* "fullText":{
* "type": "unified",
* "fragment_size" : 300,
* "number_of_fragments" : 0,
* "no_match_size": 2
* }
* }
* }
* }
* @throws IOException
*/
public QueryResult searchForHighlightBoolQuery(String indexName, Map<String, List<QueryBuilder>> terms) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
//Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
//Assert.notNull(terms, "范围查询条件terms不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 设置复合查询
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
for (String key: terms.keySet()) {
switch (key) {
case "must":
List<QueryBuilder> mustQbs = terms.get(key);
for(QueryBuilder qb: mustQbs) {
boolQueryBuilder.must(qb);
}
continue;
case "filter":
List<QueryBuilder> filterQbs = terms.get(key);
for(QueryBuilder qb: filterQbs) {
boolQueryBuilder.filter(qb);
}
continue;
case "mustNot":
List<QueryBuilder> mustNotQbs = terms.get(key);
for(QueryBuilder qb: mustNotQbs) {
boolQueryBuilder.mustNot(qb);
}
continue;
case "should":
List<QueryBuilder> shouldQbs = terms.get(key);
for(QueryBuilder qb: shouldQbs) {
boolQueryBuilder.should(qb);
}
continue;
default:
break;
}
}
sourceBuilder.query(boolQueryBuilder);
// 高亮构造器
HighlightBuilder highlightBuilder = new HighlightBuilder();
// 全局设置
highlightBuilder.numOfFragments(1);
highlightBuilder.fragmentSize(900);
// 自定义高亮标签
highlightBuilder.preTags("<em class='searcHighlight'>");
highlightBuilder.postTags("</em>");
HighlightBuilder.Field highlightFullText =new HighlightBuilder.Field("fullText");
// 设置显示器。支持unified、plain、fvh。默认unified
highlightFullText.highlighterType("fvh");
// 设置片段长度,默认100
highlightFullText.fragmentOffset(300);
// 设置返回的片段数, 默认5
highlightFullText.numOfFragments(10);
highlightBuilder.field(highlightFullText);
// 添加更多高亮字段
//HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("ip_addr");
//highlightBuilder.field(highlightUser);
// 设置高亮构造器
sourceBuilder.highlighter(highlightBuilder);
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error("复合匹配高亮检索异常。索引名称【{}】", indexName, e);
}
return qr;
}
/**
* 复合匹配--高亮分页检索
* @param indexName 索引名称
* @param fieldName 查询目标字段
* @param bool 支持
* must 必须出现在匹配的文档中,并有助于得分
* filter 必须出现在匹配的文档中。但是不同于 must查询的分数将被忽略。过滤器子句在过滤器上下文中执行,这意味着忽略评分并考虑使用子句进行高速缓存
* should 应出现在匹配的文档中
* must_not不得出现在匹配的文档中
* @return SQL翻译 select * from xxx_table where age >=18 and age<20 and name not in(name1,name2)
* POST _search
* {
* "query": {
* "bool" : {
* "must" : {
* "term" : { "user" : "kimchy" }
* },
* "filter": {
* "term" : { "tag" : "tech" }
* },
* "must_not" : {
* "range" : {
* "age" : { "gte" : 10, "lte" : 20 }
* }
* },
* "should" : [
* { "term" : { "tag" : "wow" } },
* { "term" : { "tag" : "elasticsearch" } }
* ],
* "minimum_should_match" : 1,
* "boost" : 1.0
* }
* },
* "highlight": {
* "pre_tags": "<em>",
* "post_tags": "</em>",
* "fields": {
* "fullText":{
* "type": "unified",
* "fragment_size" : 300,
* "number_of_fragments" : 0,
* "no_match_size": 2
* }
* }
* }
* }
* @throws IOException
*/
public QueryResult searchForHighlightBoolQuery(String indexName, int offset, int pageSize, Map<String, List<QueryBuilder>> terms) {
QueryResult qr = new QueryResult(Boolean.TRUE);
try {
Assert.notNull(indexName, "索引名称indexName不能为空");
//Assert.notNull(fieldName, "查询目标属性fieldName不能为空");
//Assert.notNull(terms, "范围查询条件terms不能为空");
SearchRequest searchRequest = new SearchRequest();
// 设置要查询的索引名称
searchRequest.indices(indexName);
// 构造查询器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 设置复合查询
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
for (String key: terms.keySet()) {
switch (key) {
case "must":
List<QueryBuilder> mustQbs = terms.get(key);
for(QueryBuilder qb: mustQbs) {
boolQueryBuilder.must(qb);
}
continue;
case "filter":
List<QueryBuilder> filterQbs = terms.get(key);
for(QueryBuilder qb: filterQbs) {
boolQueryBuilder.filter(qb);
}
continue;
case "mustNot":
List<QueryBuilder> mustNotQbs = terms.get(key);
for(QueryBuilder qb: mustNotQbs) {
boolQueryBuilder.mustNot(qb);
}
continue;
case "should":
List<QueryBuilder> shouldQbs = terms.get(key);
for(QueryBuilder qb: shouldQbs) {
boolQueryBuilder.should(qb);
}
continue;
default:
break;
}
}
sourceBuilder.query(boolQueryBuilder);
// 高亮构造器
HighlightBuilder highlightBuilder = new HighlightBuilder();
// 全局设置
highlightBuilder.numOfFragments(5);
highlightBuilder.fragmentSize(100);
// 自定义高亮标签
highlightBuilder.preTags("<em class='searcHighlight'>");
highlightBuilder.postTags("</em>");
HighlightBuilder.Field highlightFullText =new HighlightBuilder.Field("fullText");
// 设置显示器。支持unified、plain、fvh。默认unified
highlightFullText.highlighterType("fvh");
// 设置片段长度,默认100
highlightFullText.fragmentOffset(100);
// 设置返回的片段数, 默认5
highlightFullText.numOfFragments(5);
highlightBuilder.field(highlightFullText);
// 添加更多高亮字段
//HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("ip_addr");
//highlightBuilder.field(highlightUser);
// 设置高亮构造器
sourceBuilder.highlighter(highlightBuilder);
// 设置分页
sourceBuilder.from(offset).size(pageSize);
// 执行查询
excuteQuery(searchRequest, sourceBuilder, qr);
} catch (Exception e) {
log.error("复合匹配高亮分页检索异常。索引名称【{}】", indexName, e);
}
return qr;
}
/**
* 执行查询并设置相关参数
* @throws IOException
*/
public void excuteQuery(SearchRequest searchRequest, SearchSourceBuilder sourceBuilder, QueryResult qr) throws IOException {
// 设置超时
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
// 按查询评分降序 排序支持四种:Field-, Score-, GeoDistance-, ScriptSortBuilder
sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
// 设置查询器
searchRequest.source(sourceBuilder);
// 执行查询
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
// 封装查询结果
doQueryResult(searchResponse, qr);
}
/**
* 查询结果封装
*/
public void doQueryResult(SearchResponse searchResponse, QueryResult qr) {
// 查询耗时
TimeValue took = searchResponse.getTook();
qr.setTook(took.getMillis());
// 是否超时
qr.setTimedout(searchResponse.isTimedOut());
// 查询总数
qr.setHitsTotal(searchResponse.getHits().getTotalHits().value);
// 最高评分
qr.setMaxScore(searchResponse.getHits().getMaxScore());
// 分片信息
Map<String, Integer> shardsInfo = new HashMap<String, Integer>();
shardsInfo.put("total", searchResponse.getTotalShards());
shardsInfo.put("successful", searchResponse.getSuccessfulShards());
shardsInfo.put("skipped", searchResponse.getSkippedShards());
shardsInfo.put("failed", searchResponse.getFailedShards());
qr.setShardsInfo(shardsInfo);
// 获取查询结果
List<Map<String, Object>> hitsBody = new ArrayList<Map<String, Object>>();
SearchHits termhts=searchResponse.getHits();
for(SearchHit hit:termhts){
Map<String, Object> hitMap = hit.getSourceAsMap();
// 高亮内容封装
if(hitMap!= null) {
Map<String, HighlightField> highMap = hit.getHighlightFields();
Map<String, String> highTextMap = new HashMap<String, String>();
if(highMap != null) {
for (String highKey: highMap.keySet()) {
String fieldName = highMap.get(highKey).getName();
Text highText = (highMap.get(highKey).fragments())[0];
highTextMap.put(fieldName, highText.toString());
}
hitMap.put("highlight", highTextMap);
}
}
hitsBody.add(hitMap);
}
qr.setHitsBody(hitsBody);
}
}
最后
以上就是奋斗含羞草为你收集整理的elasticsearch7.0.1-Java RestClient API【伸手党福利】【基于Springboot2.1.3集成。非常详细的注释可直接在生产环境中使用】的全部内容,希望文章能够帮你解决elasticsearch7.0.1-Java RestClient API【伸手党福利】【基于Springboot2.1.3集成。非常详细的注释可直接在生产环境中使用】所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复