【ElasticSearch】ElasticSearch Java API的使用——常用索引、文档、查询操作(二)

【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查询、范围查询、模糊查询、高亮查询以及聚合查询。

  • 27
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值