ElasticSearch查询操作
本文大纲
一、ElasticSearch查询总结
二、ElasticSearch索引操作
三、ElasticSearch文档操作
四、ElasticSearch聚合查询
一、ElasticSearch查询总结
1.词条查询2.等值查询-term
3.多值查询-terms
5.范围查询-range
6.前缀查询-prefix
7.通配符查询-wildcard
8.复合查询
9.布尔查询
10.Filter查询
11.聚合查询
12.最值、平均值、求和
13.去重查询
14.分组聚合
15.单条件分组
16.多条件分组
17.过滤聚合
ElasticSearch的数据类型
二、ElasticSearch索引查询操作
添加依赖
<dependencies>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.8.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.8.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.8.0</version>
</dependency>
</dependencies>
索引操作
package es;
import com.es.EsDemoApplication;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.io.IOException;
import java.util.Map;
/**
* @description 索引测试
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = EsDemoApplication.class)
public class IndexTest {
@Autowired
private RestHighLevelClient client;
private static final String PERSON_INDEX = "person";
private static final int START_OFFSET = 0;
private static final int MAX_COUNT = 2000;
/**
* 查询索引
*/
@Test
public void queryIndex() throws IOException {
IndicesClient indices = client.indices();
GetIndexRequest getRequest = new GetIndexRequest("person");
GetIndexResponse response = indices.get(getRequest, RequestOptions.DEFAULT);
System.out.println(response.getMappings());
Map mappings = response.getMappings();
//iter 提示foreach
for (Object key : mappings.keySet()) {
System.out.println(key + "===" + mappings.get(key));
}
}
/**
* 添加索引
*
* @throws IOException e
*/
@Test
public void addIndex() throws IOException {
//1.使用client获取操作索引对象
IndicesClient indices = client.indices();
//2.具体操作获取返回值
//2.1 设置索引名称
CreateIndexRequest createIndexRequest = new CreateIndexRequest("persons");
CreateIndexResponse createIndexResponse = indices.create(createIndexRequest, RequestOptions.DEFAULT);
//3.根据返回值判断结果
System.out.println(createIndexResponse);
}
}
三、ElasticSearch文档操作
package es;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.Test;
import java.io.IOException;
import java.util.Arrays;
/**
* @description ES条件查询
*/
//@RunWith(SpringJUnit4ClassRunner.class)
//@SpringBootTest(classes = EsDemoApplication.class)
@Slf4j
public class QueryTest {
// @Autowired
// private RestHighLevelClient client;
private static final String PERSON_INDEX = "person";
private static final int START_OFFSET = 0;
private static final int MAX_COUNT = 2000;
/**
*
*/
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("", 9200)));
SearchRequest searchRequest = new SearchRequest(PERSON_INDEX);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
/**
* 通过id查询文档
*
* @throws IOException e
*/
@Test
public void queryDocumentById() throws IOException {
GetRequest getRequest = new GetRequest(PERSON_INDEX, "1");
GetResponse response = client.get(getRequest, RequestOptions.DEFAULT);
System.out.println("geqPersonById================》" + JSONObject.toJSON(response));
}
/**
* term等值查询,等同于 = 查询
*
* @throws IOException e
*/
@Test
public void termQueryTest() throws IOException {
searchSourceBuilder.query(QueryBuilders.termQuery("sect.keyword", "明教"));
System.out.println("searchSourceBuilder=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* constantScoreQuery,不打分查询
*
* @throws IOException e
*/
@Test
public void constantScoreQueryTest() throws IOException {
// 这样构造的查询条件,将不进行score计算,从而提高查询效率
searchSourceBuilder.query(QueryBuilders.constantScoreQuery(QueryBuilders.termQuery("sect.keyword", "明教")));
System.out.println("searchSourceBuilder=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* terms多值查询,等同于 in 查询
*
* @throws IOException e
*/
@Test
public void termsQueryTest() throws IOException {
searchSourceBuilder.query(QueryBuilders.termsQuery("sect.keyword", Arrays.asList("明教", "武当派")));
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* 范围查询,等同于between...and...
* select * from persons where age between 10 and 30
*
* @throws IOException e
*/
@Test
public void rangeQueryTest() throws IOException {
// 构建查询语句
searchSourceBuilder.query(QueryBuilders.rangeQuery("age").gte(10).lte(30));
System.out.println("查询语句=====================" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* 前缀查询,等同于 李%
* select * from person where sect like ‘武当%’
*
* @throws IOException e
*/
@Test
public void prefixQueryTest() throws IOException {
// 构建查询语句
searchSourceBuilder.query(QueryBuilders.prefixQuery("sect.keyword", "武当"));
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* 通配符查询,等同于 %无%
*
* @throws IOException e
*/
@Test
public void wildcardQueryTest() throws IOException {
// 构建查询语句
searchSourceBuilder.query(QueryBuilders.wildcardQuery("sect.keyword", "张*忌"));
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* 布尔查询,构造多条件查询
*
* @throws IOException e
*/
@Test
public void boolQueryTest() throws IOException {
// 构建查询语句
searchSourceBuilder.query(QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("sex", "女"))
.must(QueryBuilders.termQuery("sect.keyword", "明教"))
);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
@Test
public void boolQueryTest2() throws IOException {
// 构建查询语句
searchSourceBuilder.query(QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("sex", "女"))
.should(QueryBuilders.termQuery("address.word", "峨眉山"))
.should(QueryBuilders.termQuery("sect.keyword", "明教"))
.minimumShouldMatch(1)
);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
@Test
public void boolQueryTest3() throws IOException {
// 构建查询语句
searchSourceBuilder.query(QueryBuilders.boolQuery()
.must(QueryBuilders.rangeQuery("age").gte(10).lte(30))
.must(QueryBuilders.termQuery("sect.keyword", "明教"))
.filter(QueryBuilders.termQuery("sex", "男"))
);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* filter直接包含查询语句
*
* @throws IOException e
*/
@Test
public void filterTest() throws IOException {
// 构建查询语句
searchSourceBuilder.query(QueryBuilders.boolQuery()
.filter(QueryBuilders.termQuery("sex", "男"))
);// 构建查询语句
searchSourceBuilder.query(QueryBuilders.boolQuery()
.filter(QueryBuilders.termQuery("sex", "男"))
);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* filter与must等同级使用
*
* @throws IOException e
*/
@Test
public void filterTest2() throws IOException {
// 构建查询语句
searchSourceBuilder.query(QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("sect.keyword", "明教"))
.filter(QueryBuilders.termQuery("sex", "女"))
);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* filter包含must等
*
* @throws IOException e
*/
@Test
public void filterTest3() throws IOException {
// 构建查询语句
searchSourceBuilder.query(QueryBuilders.boolQuery()
.filter(QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("sect.keyword", "明教"))
.must(QueryBuilders.rangeQuery("age").gte(20).lte(35))
.mustNot(QueryBuilders.termQuery("sex.keyword", "女")))
);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* filter
*
* @throws IOException e
*/
@Test
public void filterTest4() throws IOException {
// 构建查询语句
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("sex", "女"))
.must(QueryBuilders.rangeQuery("age").gte(30).lte(40))
.mustNot(QueryBuilders.termQuery("sect.keyword", "明教"))
.should(QueryBuilders.termQuery("address.keyword", "峨眉山"))
.should(QueryBuilders.rangeQuery("power.keyword").gte(50).lte(80))
.minimumShouldMatch(1);
searchSourceBuilder.query(boolQueryBuilder);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* match:单条件匹配
*
* @throws IOException e
*/
@Test
public void matchQueryTest() throws IOException {
// 构建查询语句
searchSourceBuilder.query(QueryBuilders.matchQuery("name", "殷素素"));
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* multiMatch:多field对同一个text匹配
*
* @throws IOException e
*/
@Test
public void multiMatchQueryTest() throws IOException {
// operator传入AND或OR,决定了多个匹配条件之间的关系是与还是或
searchSourceBuilder.query(QueryBuilders.multiMatchQuery("武当", "sect", "address")
.operator(Operator.valueOf("AND"))
.minimumShouldMatch("50%"));
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
}
四、ElasticSearch聚合查询
package es;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.Test;
import org.springframework.cglib.beans.BeanMap;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @description ES聚合查询
*/
@Slf4j
public class AggTest {
/*
* 初始化客户端
*/
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("", 9200)));
// 根据索引构造查询请求
SearchRequest searchRequest = new SearchRequest(PERSON_INDEX);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
private static final String PERSON_INDEX = "person";
private static final int START_OFFSET = 0;
private static final int MAX_COUNT = 2000;
/**
* 统计查询:max、min、sum、avg、count
*
* @throws IOException e
*/
@Test
public void maxQueryTest() throws IOException {
AggregationBuilder maxBuilder = AggregationBuilders.max("max_age").field("age");
// AggregationBuilder minBuilder = AggregationBuilders.min("min_age").field("age");
// AggregationBuilder avgBuilder = AggregationBuilders.avg("min_age").field("age");
// AggregationBuilder sumBuilder = AggregationBuilders.sum("min_age").field("age");
// AggregationBuilder countBuilder = AggregationBuilders.count("min_age").field("age");
searchSourceBuilder.size(5);
searchSourceBuilder.aggregation(maxBuilder);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* stats:一并求max、min、sum、count、avg
* extendedStats:追加方差、标准差等
*
* @throws IOException e
*/
@Test
public void statsQueryTest() throws IOException {
AggregationBuilder aggBuilder = AggregationBuilders.stats("person_stats").field("age");
// AggregationBuilder aggBuilder = AggregationBuilders.extendedStats("person_stats").field("age");
SearchRequest searchRequest = new SearchRequest(PERSON_INDEX);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.aggregation(aggBuilder);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* 先查询,再统计
*
* @throws IOException e
*/
@Test
public void queryAndAggQueryTest() throws IOException {
SearchRequest searchRequest = new SearchRequest("person");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 对条件查询的结果进行统计
AggregationBuilder maxBuilder = AggregationBuilders.max("max_age").field("age");
searchSourceBuilder.query(QueryBuilders.termQuery("sect.keyword", "明教"));
searchSourceBuilder.aggregation(maxBuilder);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* 去重查询
*
* @throws IOException e
*/
@Test
public void cardinalityQueryTest() throws IOException {
AggregationBuilder aggBuilder = AggregationBuilders.cardinality("sect_count").field("sect.keyword");
SearchRequest searchRequest = new SearchRequest("person");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// searchSourceBuilder.size(0);
searchSourceBuilder.aggregation(aggBuilder);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* 分组查询
*
* @throws IOException e
*/
@Test
public void groupQueryTest() throws IOException {
SearchRequest searchRequest = new SearchRequest("person");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.size(0);
// 按sect分组
AggregationBuilder aggBuilder = AggregationBuilders.terms("sect_count").field("sect.keyword");
searchSourceBuilder.aggregation(aggBuilder);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
@Test
public void TermGroupQueryTest() throws IOException {
SearchRequest searchRequest = new SearchRequest("person");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.size(0);
// 按sex分组
AggregationBuilder ageAggBuilder = AggregationBuilders.avg("age_avg").field("age");
searchSourceBuilder.query(QueryBuilders.termQuery("sex", "女"));
searchSourceBuilder.aggregation(ageAggBuilder);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* 多字段分组
*
* @throws IOException e
*/
@Test
public void multiGroupQueryTest() throws IOException {
SearchRequest searchRequest = new SearchRequest("person");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.size(0);
// 按sect分组
AggregationBuilder sexAggBuilder = AggregationBuilders.terms("sex_count").field("sex.keyword");
AggregationBuilder sectAggBuilder = AggregationBuilders.terms("sect_count").field("sect.keyword")
.subAggregation(sexAggBuilder);
searchSourceBuilder.aggregation(sectAggBuilder);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
@Test
public void multiGroupQueryTest2() throws IOException {
SearchRequest searchRequest = new SearchRequest("person");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.size(0);
// 先按性别分组
AggregationBuilder sexAggBuilder = AggregationBuilders.terms("sex_count").field("sex.keyword");
// 再按sect分组
AggregationBuilder sectAggBuilder = AggregationBuilders.terms("sect_count").field("sect.keyword");
// 求平均年龄
AggregationBuilder ageAggBuilder = AggregationBuilders.avg("age_avg").field("age");
sexAggBuilder.subAggregation(sectAggBuilder);
sexAggBuilder.subAggregation(ageAggBuilder);
searchSourceBuilder.aggregation(sexAggBuilder);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
@Test
public void multiGroupQueryTest3() throws IOException {
SearchRequest searchRequest = new SearchRequest("person");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.size(0);
// 求平均年龄
AggregationBuilder ageAggBuilder = AggregationBuilders.range("age_avg").field("age")
.addRange(20, 40)
.addRange(40, 60)
.addRange(60, 120);
searchSourceBuilder.aggregation(ageAggBuilder);
System.out.println("查询语句=====================》" + searchSourceBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查询结果=====================》" + JSONObject.toJSON(response));
}
/**
* bean转为map
*
* @param bean bean
* @param <T> T
* @return T
*/
public static <T> Map<String, Object> beanToMap(T bean) {
Map<String, Object> map = new HashMap<>();
if (bean != null) {
BeanMap beanMap = BeanMap.create(bean);
for (Object key : beanMap.keySet()) {
if (beanMap.get(key) != null)
map.put(key + "", beanMap.get(key));
}
}
return map;
}
}