这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战。
(持续更新....)
昨天学习了ElasticSearch的多条件查询,对查询有了基本的理解,但是这只限于控制台,其实开发过程中需要Java代码实现ElasticSearch查询。
本文基于ElasticSearch和kabana的7.x版本。
一、java查询应用
1、添加RestHighLevelClient依赖
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.13.4</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.13.4</version>
</dependency>
2、配置RestHighLevelClient
@Configuration
public class ElasticSearchConfig {
@Value("${xxxx.host}")
private String hostname;
@Value("${xxxx.port}")
private int port;
@Value("${xxxx.user}")
private String user;
@Value("${xxxx.password}")
private String password;
@Value("${xxxx.timeout}")
private long socketTimeout;
@Value("${xxxx.scheme}")
private String scheme;
public static final RequestOptions COMMON_OPTIONS;
static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
COMMON_OPTIONS = builder.build();
}
/**
* 使用账号密码连接
**/
public RestHighLevelClient restClient() {
RestClientBuilder builder = RestClient.builder(
new HttpHost(hostname, port, scheme));
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(user, password));
builder.setHttpClientConfigCallback(f -> f.setDefaultCredentialsProvider(credentialsProvider));
return new RestHighLevelClient(builder);
}
}
3、组装查询条件--分页
@Autowired
RestHighLevelClient esSafeRestClient;
SearchSourceBuilder builder = new SearchSourceBuilder();
EsQueryBuilderUtil.setPage(requestOptions);
builder.from(requestOptions.getPageNum()-1);
builder.size(requestOptions.getPageSize());
BoolQueryBuilder must = QueryBuilders.boolQuery();
//组装查询条件
TermsQueryBuilder queryBuilder = QueryBuilders.termsQuery("workOrderFlowId", id);
...
//时间降序
builder.sort(new FieldSortBuilder("startTime").order(SortOrder.DESC));
builder.trackTotalHits(true);
builder.query(must);
4、查询处理
String index = "t_xxxx_xx";
SearchRequest request = new SearchRequest(new String[]{index});
CountRequest countRequest = new CountRequest(new String[]{index});
countRequest.source(builder);
request.source(builder);
try {
SearchResponse response = this.esSafeRestClient.search(request, ElasticSearchConfig.COMMON_OPTIONS);
this.esSafeRestClient.count(countRequest, RequestOptions.DEFAULT);
SearchHits hits1 = response.getHits();
long length = hits1.getTotalHits().value;
SearchHit[] hits2 = hits1.getHits();
List<T> retList = new ArrayList(hits2.length);
SearchHit[] var13 = hits2;
int var14 = hits2.length;
for(int var15 = 0; var15 < var14; ++var15) {
SearchHit hit = var13[var15];
String strJson = hit.getSourceAsString();
retList.add(JSON.parseObject(strJson, reference, new Feature[0]));
}
EsPageDto<T> pageDto = new EsPageDto();
pageDto.setTotal(length);
pageDto.setList(retList);
return pageDto;
} catch (Exception var18) {
var18.printStackTrace();
throw new RuntimeException(var18);
}
二、几种查询方法封装
//range query
//范围查询
//QueryBuilders.rangeQuery("hotelNo") .gt("10143262306")//大于 10143262306
// .lt("101432623062055348221") //小于 101432623062055348221
// .includeLower(true) //包括下界
// .includeUpper(false); //包括上界
public void rangeQuery(String name, Long startTime, Long endTime, BoolQueryBuilder must) {
must.must(QueryBuilders.rangeQuery(name).from(startTime).to(endTime));
}
// exist query 查询字段不为null的文档 如查询字段name 不为null的数据
public void existQuery(String name, BoolQueryBuilder must) {
must.must(QueryBuilders.existsQuery(name));
}
// mustNot 查询没有字段或值为null或没有值的文档
public void notExistQuery(String name, BoolQueryBuilder must) {
must.mustNot(QueryBuilders.existsQuery(name));
}
//prefix query 匹配分词前缀 如果字段没分词,就匹配整个字段前缀
public void prefixQuery(String name, String value, BoolQueryBuilder must) {
must.must(QueryBuilders.prefixQuery(name, value));
}
//matchAllQuery匹配所有
//matchPhraseQuery对中文精确匹配
//matchQuery("key", Obj) 单个匹配, field不支持通配符, 前缀具高级特性
public void matchPhraseQuery(String name, Object value, BoolQueryBuilder must) {
if (!Objects.isNull(value)) {
must.must(QueryBuilders.matchPhraseQuery(name, value));
}
}
//multiMatchQuery("text", "field1", "field2"..); 一个值匹配多个字段, field有通配符忒行
public void multiMatchQuery(String field1, String field2,String field3,Object value, BoolQueryBuilder must) {
if (!Objects.isNull(value)) {
must.must(QueryBuilders.multiMatchQuery(value, field1, field2, field3));
}
}
//matchPhraseQuery对中文精确匹配前缀
public void matchPhrasePrefixQuery(String name, Object value, BoolQueryBuilder must) {
if (!Objects.isNull(value)) {
must.must(QueryBuilders.matchPhrasePrefixQuery(name, value));
}
}
//分词精确查询
public void termQuery(String name, Object value, BoolQueryBuilder must) {
if (!Objects.isNull(value)) {
must.must(QueryBuilders.termQuery(name, value));
}
}
//terms Query 多term查询,匹配多个值
public void termsQuery(String name, List<String> value, BoolQueryBuilder must) {
if (!Objects.isNull(value)) {
must.must(QueryBuilders.termsQuery(name, value));
}
}
//组合查询
//* must: AND
//* mustNot: NOT
//* should:: OR
public void shouldQuery(String name, Object value, BoolQueryBuilder must) {
if (!Objects.isNull(value)) {
must.should(QueryBuilders.termsQuery(name, value));
}
}
// 模糊查询
//wildcard query 通配符查询,支持* 任意字符串;?任意一个字符
public void wildcardQuery(String name, Object value, BoolQueryBuilder must) {
if (!Objects.isNull(value)) {
must.must(QueryBuilders.wildcardQuery(name+".keyword", "*" + value+"*"));
}
}
//regexp query 正则表达式匹配分词
public void regexpQuery(String name, Object value, BoolQueryBuilder must) {
if (!Objects.isNull(value)) {
must.must(QueryBuilders.regexpQuery(name, "../"));
}
}
//fuzzy query 分词模糊查询,通过增加fuzziness 模糊属性,来查询term
// 如下 能够匹配 name 为 te el tel前或后加一个字母的term的
// 文档 fuzziness 的含义是检索的term 前后增加或减少n个单词的匹配查询
public void fuzzyQuery(String name, Object value, BoolQueryBuilder must) {
if (!Objects.isNull(value)) {
must.must(QueryBuilders.fuzzyQuery(name, value).fuzziness(Fuzziness.ONE));
}
}
三、聚合查询
聚合函数:使用AggregationBuilders
AggregationBuilder aggregation =
AggregationBuilders.terms("as_code").field("code.keyword")
.subAggregation(AggregationBuilders.terms("group_category").field("category") .subAggregation(AggregationBuilders.max("max_index").field("traffic_index"))
)
.size(Integer.MAX_VALUE);
//统计code个数,去重
AggregationBuilders.cardinality("distinct_code").field("code");
//统计最大分
AggregationBuilders.max("max_score").field("score");
//统计最小分
AggregationBuilders.min("min_score").field("score");
//统计总分和
AggregationBuilders.sum("sum_score").field("score");
//统计平均分
AggregationBuilders.avg("avg_score").field("score");
四、查询指定几个字段
setFetchSource(String[] includes, String[] excludes)方法指定所需的字段 sourceBuilder.fetchSource("shop_code", null);//过滤门店编码为null数据
SearchResponse response = client.prepareSearch("my-index")
.setTypes("my-type")
.setSearchType(SearchType.QUERY_AND_FETCH)
.setFetchSource(new String[]{"field1"}, null)
.setQuery(QueryBuilders.termsQuery("field1", "1234"))
.execute()
.actionGet();
for (SearchHit hit : response.getHits()){
Map map = hit.getSource();
map.toString();
}
今天就到这里,明天继续。