【ElasticSearch】ElasticSearch Java API的使用——常用索引、文档、查询操作(二)
前言
Elaticsearch,简称为es,es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别(大数据时代)的数据。es也使用java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。
docker部署ElasticSearch、ElasticSearch基本Restful API的使用可以参考:
【ElasticSearch】docker部署ElasticSearch、常用Restful API的使用(一)
一、环境准备
1.1 导入相关依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.13</version>
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<elasticsearch.version>7.4.0</elasticsearch.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
1.2 配置类ElasticSearchConfig
配置RestHighLevelClient
,并将其放入spring容器中
@Configuration
public class ElasticSearchConfig {
// 注册 rest高级客户端
@Bean
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("ip",9200,"http")
)
);
return client;
}
}
1.3 案例使用实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
private static final long serialVersionUID = -3843548915035470817L;
private String name;
private Integer age;
private String gender;
}
1.4 案例使用测试类
@RunWith(SpringRunner.class) // 实现Spring Boot单元测试
@SpringBootTest // 标记Spring Boot测试,并加载应用容器
public class ESTest {
@Autowired
public RestHighLevelClient restHighLevelClient;
}
二、ElasticSearch Java API
2.1 索引操作
2.1.1 创建索引
创建CreateIndexRequest
,通过 restHighLevelClient.indices().create(request, RequestOptions.DEFAULT)
发送create请求,创建索引
// 测试索引的创建 CreateIndexRequest
@Test
public void testCreateIndex() throws IOException {
//创建 生成索引请求对象
CreateIndexRequest request = new CreateIndexRequest("user");
//发送请求,获取响应
CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
System.out.println(response.isAcknowledged());// 查看响应状态,是否创建成功
System.out.println(response);// 查看返回对象
restHighLevelClient.close();
}
2.1.2 查询索引
创建GetIndexRequest
,通过restHighLevelClient.indices().get(request, RequestOptions.DEFAULT)
发送get请求,获取索引
// 测试获取索引 GetIndexRequest
@Test
public void testGetIndex() throws IOException {
//创建 查询索引请求对象
GetIndexRequest request = new GetIndexRequest("user");
//查询索引是否存在
boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists);// 索引是否存在
//发送请求 获取响应
GetIndexResponse response = restHighLevelClient.indices().get(request, RequestOptions.DEFAULT);
System.out.println("aliases:"+response.getAliases());
System.out.println("mappings:"+response.getMappings());
System.out.println("settings:"+response.getSettings());
restHighLevelClient.close();
}
/**
* true
* aliases:{user=[]}
* mappings:{user=org.elasticsearch.cluster.metadata.MappingMetaData@db6ebd25}
* settings:{user={"index.creation_date":"1704877114426","index.number_of_replicas":"1","index.number_of_shards":"1","index.provided_name":"user","index.uuid":"lVwb2pnjQgaXfXadO_vPdA","index.version.created":"7040099"}}
*/
2.1.3 删除索引
创建DeleteIndexRequest
,通过restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT)
发送delete请求,删除索引
// 测试索引删除
@Test
public void testDeleteIndex() throws IOException {
//创建 删除是所有请求对象
DeleteIndexRequest request = new DeleteIndexRequest("user");
//发送删除请求 返回响应
AcknowledgedResponse response = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
System.out.println(response.isAcknowledged());// 是否删除成功
restHighLevelClient.close();
}
2.2 文档操作
2.2.1 添加文档
创建IndexRequest
(设置索引名称),将对象转为json字符串放入source中( request.source(JSON.toJSONString(user), XContentType.JSON)
),通过restHighLevelClient.index(request, RequestOptions.DEFAULT)
发送请求
// 测试添加文档(先创建一个User实体类,添加fastjson依赖)
@Test
public void testAddDocument() throws IOException {
// 创建一个User对象
User user = new User("chandler", 18, "male");
// 创建请求
IndexRequest request = new IndexRequest("user");
// 制定规则 PUT /user_index/_doc/1
request.id("1");// 设置文档ID
request.timeout(TimeValue.timeValueMillis(1000));// request.timeout("1s")
// 将我们的数据放入请求中
request.source(JSON.toJSONString(user), XContentType.JSON);
// 客户端发送请求,获取响应的结果
IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
System.out.println(response.status());// 获取建立索引的状态信息 CREATED
System.out.println(response);
// 查看返回内容 IndexResponse[index=user_index,type=_doc,id=1,version=1,result=created,seqNo=0,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]
// 再次运行(添加),version改变:IndexResponse[index=user_index,type=_doc,id=1,version=2,result=updated,seqNo=1,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]
}
2.2.2 查询文档
创建GetRequest
(设置索引名及文档主键id),restHighLevelClient.get(request, RequestOptions.DEFAULT)
发送请求返回响应对象,通过response.getSourceAsString()
获取source中存储的对象json字符串
// 测试获得文档信息
@Test
public void testGetDocument() throws IOException {
GetRequest request = new GetRequest("user_index","1");
GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
System.out.println(response.getSourceAsString());// 打印文档内容 {"age":18,"name":"chandler"}
System.out.println(request);// 返回的全部内容和命令是一样的 get [user_index][_doc][1]: routing [null]
String userJSON = response.getSourceAsString();
User user = JSON.parseObject(userJSON, User.class);
System.out.println(user);
restHighLevelClient.close();
}
2.2.3 判断文档是否存在
创建GetRequest
(设置索引名及文档主键id),restHighLevelClient.exists(request, RequestOptions.DEFAULT)
返回文档是否存在
// 获取文档,判断是否存在 get /user_index/_doc/1
@Test
public void testDocumentIsExists() throws IOException {
GetRequest request = new GetRequest("user_index", "1");
// 不获取返回的 _source的上下文了
request.fetchSourceContext(new FetchSourceContext(false));
request.storedFields("_none_");
boolean exists = restHighLevelClient.exists(request, RequestOptions.DEFAULT);
System.out.println(exists);//true
}
2.2.4 更新文档内容
创建UpdateRequest
对象,设置文档内容request.doc(JSON.toJSONString(user),XContentType.JSON)
,发送更新请求restHighLevelClient.update(request, RequestOptions.DEFAULT)
// 测试更新文档内容
@Test
public void testUpdateDocument() throws IOException {
UpdateRequest request = new UpdateRequest("user_index", "1");
User user = new User("monica",27, "female");
request.doc(JSON.toJSONString(user),XContentType.JSON);
UpdateResponse response = restHighLevelClient.update(request, RequestOptions.DEFAULT);
System.out.println(response.status()); // OK
restHighLevelClient.close();
}
2.2.5 删除文档
创建DeleteRequest
,发送delete请求restHighLevelClient.delete(request, RequestOptions.DEFAULT)
// 测试删除文档
@Test
public void testDeleteDocument() throws IOException {
DeleteRequest request = new DeleteRequest("user_index", "1");
request.timeout("1s");
DeleteResponse response = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
System.out.println(response.status());// OK
}
2.2.6 批量操作
创建批量请求对象BulkRequest
,将单个对象放入bulkRequest
然后发送请求
//批量新增文档
@Test
public void testAddBatchDoc() throws IOException {
//创建数据
List<User> users = new ArrayList<>();
users.add(new User("chandler", 27, "male"));
users.add(new User("monica", 26, "female"));
users.add(new User("joey", 25, "male"));
users.add(new User("phoebe", 29, "female"));
users.add(new User("ross", 31, "male"));
users.add(new User("rachel", 29, "female"));
//生成批量请求对象——批量请求对象
BulkRequest request = new BulkRequest();
for(int i = 0; i < users.size(); i++){
User user = users.get(i);
String userJson = JSON.toJSONString(user);
//添加请求对象
request.add(new IndexRequest().index("user").id(1001 + i + "").source(userJson, XContentType.JSON));
}
//发送请求
BulkResponse response = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
restHighLevelClient.close();
}
//批量删除文档
@Test
public void testDeleteBatchDoc() throws IOException {
//生成批量请求对象——批量请求对象
BulkRequest request = new BulkRequest();
request.add(new DeleteRequest().index("user").id("1001"));
request.add(new DeleteRequest().index("user").id("1002"));
request.add(new DeleteRequest().index("user").id("1003"));
request.add(new DeleteRequest().index("user").id("1004"));
request.add(new DeleteRequest().index("user").id("1005"));
request.add(new DeleteRequest().index("user").id("1006"));
//发送请求
BulkResponse response = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
restHighLevelClient.close();
}
2.3 查询操作
2.3.1 查询所有数据
创建查询请求SearchRequest
,创建并设置查询源构建器SearchSourceBuilder
,配置查询请求源searchRequest.source(searchSourceBuilder)
,发送查询请求restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT)
//查询索引所有数据
@Test
public void testMatchAll() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//设置请求体为查询所有数据
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取查询命中的数据
SearchHits hits = searchResponse.getHits();
List<User> users = new ArrayList<>();
for(SearchHit hit : hits){
String userJson = hit.getSourceAsString();
User user = JSON.parseObject(userJson, User.class);
users.add(user);
}
System.out.println(users);
System.out.println(hits.getTotalHits());// 6 hits ——总命中数量
System.out.println(hits.getAt(1));//返回第2条命中信息
System.out.println(hits.getMaxScore());// 1.0
System.out.println(hits.getSortFields());//null
restHighLevelClient.close();
}
2.3.2 match查询数据
设置查询请求源构建器的请求为matchQuery:searchSourceBuilder.query(QueryBuilders.matchQuery("name", "chandler bing"))
@Test
public void testMatch() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//设置请求体为查询所有数据
searchSourceBuilder.query(QueryBuilders.matchQuery("name", "chandler bing"));
//大多数字段使用standard分词器,它根据空格和标点符号进行分词。
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取查询命中的数据
SearchHits hits = searchResponse.getHits();
for(SearchHit hit : hits){
System.out.println(hit.getSourceAsString());
}
restHighLevelClient.close();
}
2.3.3 term查询
设置查询请求源构建器的请求为termQuery:searchSourceBuilder.query(QueryBuilders.termQuery("gender", "female"))
//term进行不可分查询
@Test
public void testTerm() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//设置请求体为term,不可分查询gender为female的数据
searchSourceBuilder.query(QueryBuilders.termQuery("gender", "female"));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取查询命中的数据
SearchHits hits = searchResponse.getHits();
for(SearchHit hit : hits){
System.out.println(hit.getSourceAsString());
}
restHighLevelClient.close();
}
2.3.4 分页查询
searchSourceBuilder.from(0)
设置当前页的起始索引,默认从 0 开始;searchSourceBuilder.size(2)
设置每页显示条数
//分页查询
@Test
public void testFromAndSize() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//设置请求体为查询所有数据
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//设置分页
searchSourceBuilder.from(0);//当前页的起始索引,默认从 0 开始。
searchSourceBuilder.size(2);//每页显示条数
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取查询命中的数据
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());//6 hits
System.out.println(hits.getHits().length);//2
for(SearchHit hit : hits){
System.out.println(hit.getSourceAsString());
}//输出两条信息
restHighLevelClient.close();
}
2.3.5 排序查询
searchSourceBuilder.sort("age", SortOrder.ASC)
设置排序字段与排序方式
//排序查询
@Test
public void testSort() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//设置请求体为查询所有数据
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//设置排序
searchSourceBuilder.sort("age", SortOrder.ASC);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取查询命中的数据
SearchHits hits = searchResponse.getHits();
for(SearchHit hit : hits){
System.out.println(hit.getSourceAsString());
}
restHighLevelClient.close();
}
/**
* {"age":25,"gender":"male","name":"joey"}
* {"age":26,"gender":"female","name":"monica"}
* {"age":27,"gender":"male","name":"chandler"}
* {"age":29,"gender":"female","name":"phoebe"}
* {"age":29,"gender":"female","name":"rachel"}
* {"age":31,"gender":"male","name":"ross"}
*/
2.3.6 过滤字段
使用searchSourceBuilder.fetchSource(includes, excludes)
进行字段过滤
//过滤字段
@Test
public void testIncludes() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//设置请求体为查询所有数据
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//设置字段过滤
String[] includes = {"name", "age"};
String[] excludes = {};
searchSourceBuilder.fetchSource(includes, excludes);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取查询命中的数据——查询的字段只包含name、age
SearchHits hits = searchResponse.getHits();
for(SearchHit hit : hits){
System.out.println(hit.getSourceAsString());
}
restHighLevelClient.close();
}
@Test
public void testExcludes() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//设置请求体为查询所有数据
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//设置字段过滤
String[] excludes = {"gender", "age"};
String[] includes = {};
searchSourceBuilder.fetchSource(includes, excludes);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取查询命中的数据——查询的字段不包含gender、age
SearchHits hits = searchResponse.getHits();
for(SearchHit hit : hits){
System.out.println(hit.getSourceAsString());
}
restHighLevelClient.close();
}
2.3.7 bool查询
创建bool查询构造器QueryBuilders.boolQuery()
,组合查询条件must、mustnot、should、filter等,将bool查询构造器设置到查询源构造器中的查询条件中searchSourceBuilder.query(boolQueryBuilder)
//bool查询
@Test
public void testBool() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//设置bool查询
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.matchQuery("name", "chandler"));//must
boolQueryBuilder.mustNot(QueryBuilders.matchQuery("gender", "female"));//must not
boolQueryBuilder.should(QueryBuilders.matchQuery("age", 10000));//should
boolQueryBuilder.filter(QueryBuilders.rangeQuery("age").gt(18));
//给searchSourceBuilder设置query
searchSourceBuilder.query(boolQueryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取查询命中的数据
SearchHits hits = searchResponse.getHits();
for(SearchHit hit : hits){
System.out.println(hit.getSourceAsString());//{"age":27,"gender":"male","name":"chandler"}
}
restHighLevelClient.close();
}
2.3.8 范围查询
创建范围查询构造器QueryBuilders.rangeQuery("age")
并设置查询字段,设置范围查询条件rangeQueryBuilder.gte(28);rangeQueryBuilder.lt(30);
,将范围查询构造器设置到查询源构造器的query中searchSourceBuilder.query(rangeQueryBuilder)
//范围查询
@Test
public void testRange() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//设置查询方式为范围查询
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age");
rangeQueryBuilder.gte(28);//大于等于28
rangeQueryBuilder.lt(30);//小于30
//给searchSourceBuilder设置query
searchSourceBuilder.query(rangeQueryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取查询命中的数据
SearchHits hits = searchResponse.getHits();
for(SearchHit hit : hits){
System.out.println(hit.getSourceAsString());
}
restHighLevelClient.close();
}
/**
* {"age":29,"gender":"female","name":"phoebe"}
* {"age":29,"gender":"female","name":"rachel"}
*/
2.3.9 模糊查询
QueryBuilders.fuzzyQuery("name", "joe").fuzziness(Fuzziness.ONE)
:设置模糊查询字段、模糊查询值、以及编辑距离
//模糊查询
@Test
public void testFuzzy() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//设置查询方式为模糊查询
FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("name", "joe").fuzziness(Fuzziness.ONE);
searchSourceBuilder.query(fuzzyQueryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取查询命中的数据
SearchHits hits = searchResponse.getHits();
for(SearchHit hit : hits){
System.out.println(hit.getSourceAsString());
}//{"age":25,"gender":"male","name":"joey"}
restHighLevelClient.close();
}
2.3.10 高亮查询
创建高亮构造器HighlightBuilder
,设置标签前缀preTags
、标签后缀postTags
以及高亮字段field
,为查询源构造器设置高亮 searchSourceBuilder.highlighter(highlightBuilder)
//高亮查询
@Test
public void testHighlight() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//设置查询方式
TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("name", "joey");
searchSourceBuilder.query(termsQueryBuilder);
// MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
// searchSourceBuilder.query(matchAllQueryBuilder);
//设置高亮构建器
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<font color='red>");//设置标签前缀
highlightBuilder.postTags("</font>");//设置标签后缀
highlightBuilder.field("name");//设置高亮字段
//设置高亮构建对象
searchSourceBuilder.highlighter(highlightBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取查询命中的数据
SearchHits hits = searchResponse.getHits();
List<Map<String, Object>> highlightObjectMap = new ArrayList<>();
for(SearchHit hit : hits){
// System.out.println(hit.getSourceAsString());//{"age":25,"gender":"male","name":"joey"}
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
System.out.println(highlightFields);//{name=[name], fragments[[<font color='red>joey</font>]]}
// 使用新的字段值(高亮),覆盖旧的字段值
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
// System.out.println(sourceAsMap);//{gender=male, name=joey, age=25}
HighlightField name = highlightFields.get("name");
// 替换
if (name != null) {
Text[] fragments = name.fragments();
StringBuilder new_name = new StringBuilder();
for (Text text : fragments) {
new_name.append(text);
}
sourceAsMap.put("name", new_name.toString());
System.out.println(sourceAsMap);//{gender=male, name=<font color='red>joey</font>, age=25}
}
highlightObjectMap.add(sourceAsMap);
}
restHighLevelClient.close();
}
2.3.11 聚合查询
searchSourceBuilder.aggregation()
设置聚合查询
//聚合查询
@Test
public void testMetricsAggregationAvg() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//聚合查询设置
searchSourceBuilder.aggregation(AggregationBuilders.avg("avgAge").field("age")).size(0);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//注意这里要把Aggregation类型转化为ParsedAvg类型
ParsedAvg aggregation = searchResponse.getAggregations().get("avgAge");
System.out.println(aggregation.getValue()); //返回27.833333333333332
restHighLevelClient.close();
}
@Test
public void testMetricsAggregationStats() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//聚合查询设置
searchSourceBuilder.aggregation(AggregationBuilders.stats("statsAge").field("age")).size(0);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//注意这里要把Aggregation类型转化为ParsedStats类型
ParsedStats statsAge = searchResponse.getAggregations().get("statsAge");
System.out.println(statsAge.getMax());//31.0
System.out.println(statsAge.getAvg());//27.833333333333332
System.out.println(statsAge.getCount());//6
System.out.println(statsAge.getMin());//25.0
System.out.println(statsAge.getSum());//167.0
restHighLevelClient.close();
}
//桶聚合查询
@Test
public void testBucketAggregation() throws IOException {
//创建搜索请求对象
SearchRequest searchRequest = new SearchRequest().indices("user");
//创建查询请求体构建器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//聚合查询设置
searchSourceBuilder.aggregation(AggregationBuilders.terms("genderGroup").field("gender"));
// searchSourceBuilder.aggregation(AggregationBuilders.terms("genderTerm").field("gender")
// .subAggregation(AggregationBuilders.terms("ageTerm").field("age")));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//获取数据时首先对genderTerm分桶,再对ageTerm分桶
// Terms genderTerm = searchResponse.getAggregations().get("genderTerm");
// System.out.println(genderTerm);
// for(Terms.Bucket genderBucket : genderTerm.getBuckets()){
// Terms ageTerm = genderBucket.getAggregations().get("ageTerm");
// for (Terms.Bucket ageBucket : ageTerm.getBuckets()){
// System.out.println("gender:" + genderBucket.getKeyAsString() + "age:" + ageBucket.getKeyAsString() + "count:" + ageBucket.getDocCount());
// }
// }
restHighLevelClient.close();
}
//Elasticsearch - 聚合查询或者排序时出现Fielddata is disabled on text fields by default问题的解决办法
//Terms Aggregation
//就是一个最简单的分桶策略,也就是group by 策略,他是精确匹配,根据你指定的字段将值相等的文档分在一个桶中。
//terms 是精确匹配,也是不分词,所以如果你想要对 text类型的使用terms,需要将field_data 开启
}
总结
本文总结了ElasticSearch的常用Java API,包含常用的索引、文档、查询相关操作。索引操作包含索引的增、删、查;文档操作包含文档的增、删、改、查以及批量操作;查用的查询操作包含查询所有数据、match查询、term查询、分页查询、排序查询、过滤字段、bool查询、范围查询、模糊查询、高亮查询以及聚合查询。