• Springboot整合Elasticsearch(查询数据的方式)


    参考文档地址:
    Elasticsearch 官方文档地址:点击链接
    Spring Data Elasticsearch 官方文档地址:点击链接

    添加maven依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>

    1.初始化Elasticsearch

    • 在yml配置文件中配置es的连接参数(略)
    • 新建一个config类,配置es(如下)
    @Configuration
    public class ElasticsearchConfig {
    
        @Bean
        public RestHighLevelClient restHighLevelClient() {
            // 这个是springboot的文档推荐写法
    //        ClientConfiguration clientConfiguration = ClientConfiguration.builder()
    //                .connectedTo("192.168.203.129:9200").build();
    //
    //        return RestClients.create(clientConfiguration).rest();
    
            // es官方文档推荐写法
            RestHighLevelClient client = new RestHighLevelClient(
                    RestClient.builder(
                            new HttpHost("192.168.203.129", 9200, "http")));
            return client;
        }
    }

    2.简单查询

    Spring Data Elasticsearch提供了一个ElasticsearchRepository接口,可以很方便的自定义简单的查询方法。

    public interface MyRepository extends ElasticsearchRepository<User, Long> {
    
        /**
         * 根据id或者年龄或者名字查询
         * @param id
         * @param age
         * @param name
         * @return
         */
        User findByIdOrAgeOrName(Long id, Integer age, String name);
    
        /**
         * 删除年龄大于或等于给定值的数据
         * @param age
         */
        void deleteByAgeGreaterThanEqual(Integer age);
    
        /**
         * 搜索指定年龄段的user
         * @param start 开始年龄
         * @param end 结束年龄
         * @return
         */
        User findAllByAgeBetween(int start,int end);
    
    
    }

    这里要注意,自定义方法的名字是有规则的,idea会自动提示,根据提示,以及自己想要的操作,书写方法名和对应参数即可。在Spring Data Elasticsearch的文档里也有相关说明:

     

    1.1测试代码

    @Autowired  
    private MyRepository myRepository;
    
    // 查询年龄为27岁的用户数据
    @Test
    void myTest6() {
        User rico = myRepository.findByIdOrAgeOrName(null, 27, null);
        System.out.println(rico);
    }
    
    // 插入一条user数据
    @Test
    void myTest7() throws IOException {
        User user = User.builder()
                .name("rico3")
                .age(35)
                .id(3L)
                .birthday(new Date())
                .build();
    
        User save = myRepository.save(user);
        System.out.println(save);
        restHighLevelClient.close();
    }
    
    // 删除年龄大于或等于29岁的用户的数据
    @Test
    void myTest8() throws IOException {
        myRepository.deleteByAgeGreaterThanEqual(29);
        restHighLevelClient.close();
    }

    3.复杂查询

      3.1使用ElasticsearchRestTemplate

    先看测试代码

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    
    // 使用elasticsearchRestTemplate来查询数据
    @Test
    void myTest9() {
        // 创建一个query,QueryBuilders下可以选择查询方式
        NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(QueryBuilders.matchAllQuery());
        SearchHits<User> search = elasticsearchRestTemplate.search(nativeSearchQuery, User.class);
        for (org.springframework.data.elasticsearch.core.SearchHit<User> userSearchHit : search) {
            User content = userSearchHit.getContent();
            System.out.println(content);
        }
    }
    
    @Test
    void myTest11() {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withQuery(QueryBuilders.matchAllQuery());
        // 搜索age大于27的user数据,这里的写法其实和json查询语句的写法一样的,如下
        /*
        GET /bank/_search
        {
          "query": {
            "bool": {
              "must": { "match_all": {} },
              "filter": {
                "range": {
                  "balance": {
                    "gte": 20000,
                    "lte": 30000
                  }
                }
              }
            }
          }
        }
         */
        builder.withQuery(QueryBuilders.boolQuery()
                .must(QueryBuilders.matchAllQuery())
                .filter(QueryBuilders.rangeQuery("age").gte(27)));
        NativeSearchQuery query = builder.build();
        SearchHits<User> searchHits = elasticsearchRestTemplate.search(query, User.class);
        for (org.springframework.data.elasticsearch.core.SearchHit<User> searchHit : searchHits) {
            System.out.println(searchHit.getContent());
        }
    }
    
    // 查询年龄大于10岁的用户的数量
    @Test
    public void myTest14() {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.addAggregation(AggregationBuilders
                .filter("age_gt_10", QueryBuilders.rangeQuery("age").gt(10))
                .subAggregation(AggregationBuilders.count("group_by_count").field("name")));
        NativeSearchQuery searchQuery = builder.build();
        SearchHits<User> search = elasticsearchRestTemplate.search(searchQuery, User.class);
        Filter age_gt_10 = search.getAggregations().get("age_gt_10");
        Aggregations aggregations = age_gt_10.getAggregations();
        ValueCount count = aggregations.get("group_by_count");
        System.out.println(count.getValue());
    }

    ElasticsearchRestTemplate适合做一些复杂的搜索操作,比如聚合搜索等。需要注意的是,ElasticsearchRestTemplate查询返回的结果需要传入我们的数据实体类User.class

    @Data
    @Document(indexName = "users") // 将此类标记为Document,索引是users,对应es里的数据
    @Builder
    public class User {
        @Id
        private Long id;
        @Field(type = FieldType.Keyword)
        private String name;
        @Field(type = FieldType.Long)
        private Integer age;
        @Field(type = FieldType.Date,format= DateFormat.basic_date)
        private Date birthday;
    }

    还有一个需要注意:在上面的代码myTest14函数中,builder的写法需要基本是和es的json查询语句一样的,如下:

     输出结果是:

    3.2使用RestHighLevelClient

    @Autowired  
    private RestHighLevelClient restHighLevelClient;
    
    @Test
    void myTest() throws IOException {
        // 创建一个索引,并设置了id为1的文档数据
        IndexRequest request = new IndexRequest("spring-data3")
                .id("1")
                .opType(DocWriteRequest.OpType.CREATE)
                .source("name", "rico2")
                .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
        IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
        System.out.println(response.toString());
        restHighLevelClient.close();
    
    // 获取文档内容
    @Test
    void myTest4() throws IOException {
        GetRequest getRequest = new GetRequest("users", "1");
        boolean exists = restHighLevelClient.indices().exists(new GetIndexRequest(getRequest.index()), RequestOptions.DEFAULT);
        if (exists) {
            GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
            System.out.println(getResponse.getSourceAsString());
        } else {
            System.out.println("索引不存在!");
        }
        restHighLevelClient.close();
    }
    
    // 搜索index为users下的所有文档
    @Test
    void myTest5() throws IOException {
        SearchRequest searchRequest = new SearchRequest("users");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        searchRequest.source(searchSourceBuilder);
        SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
            System.out.println("=================================");
        }
    
    }
    
    // 查询users下所有用户的年龄平均值
    @Test
    public void myTest12() throws IOException {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        AvgAggregationBuilder avgAggregationBuilder = AggregationBuilders.avg("average_age").field("age");
        searchSourceBuilder.aggregation(avgAggregationBuilder);
    
        SearchRequest request = new SearchRequest("users");
        request.source(searchSourceBuilder);
    
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        Aggregations aggregations = response.getAggregations();
        Avg average_age = aggregations.get("average_age");
        System.out.println(average_age.getValue());
    }
    
    // 查询年龄大于10岁的用户的数量,使用restHighLevelClient
    @Test
    public void myTest13() throws IOException {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        FilterAggregationBuilder filter = AggregationBuilders
                .filter("age_gt_10", QueryBuilders.rangeQuery("age").gt(10));
        filter.subAggregation(AggregationBuilders.count("group_by_count").field("name"));
        searchSourceBuilder.aggregation(filter);
    
        SearchRequest request = new SearchRequest("users");
        request.source(searchSourceBuilder);
    
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        Aggregations aggregations = response.getAggregations();
        Filter age_gt_10 = aggregations.get("age_gt_10");
        Aggregations aggregations1 = age_gt_10.getAggregations();
        ValueCount group_by_count = aggregations1.get("group_by_count");
        System.out.println(group_by_count.getValue());
    }

    可以看出,RestHighLevelClient既可以做简单的查询,也可以做复杂的查询。如果只需要做简单的数据操作,还是建议用ElasticsearchRepository,代码更简单。和ElasticsearchRestTemplate一样,建立查询条件的代码要参照es的json查询语句的写法,比如这里的myTest13用的就是嵌套查询。

  • 相关阅读:
    Linux中OCI开发库的配置
    makefile中的gcc -o $@ $^是什么意思?
    【转】gcc中的-w -W和-Wall选项
    【转】Linux查看系统是32位还是64位方法总结
    【转】gcc命令中参数c和o混合使用的详解
    Python2.7设置在shell脚本中自动补全功能的方法
    Python3设置在shell脚本中自动补全功能的方法
    Pyqt图标下载网站
    如何使QLineEdit禁止编辑
    python偏函数的运用
  • 原文地址:https://www.cnblogs.com/47Gamer/p/16291802.html
Copyright © 2020-2023  润新知