Elasticsearch Java 客户端使用

Elasticsearch 7.7.1

1. elasticsearch-rest-high-level-client

添加依赖

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>7.7.1</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.7.1</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.72</version>
</dependency>

添加配置

elasticsearch:
  # 协议
  schema: http
  # 集群地址,多个用逗号隔开
  nodes: 192.168.6.101:9200
  # 连接超时时间
  connect-timeout-ms: 5000
  # Socket 连接超时时间
  socket-timeout-ms: 5000
  # 获取连接的超时时间
  connection-request-timeout-ms: 5000
  # 最大连接数
  max-connect-total: 100
  # 最大路由连接数
  max-connect-per-route: 100

初始化

@Configuration
public class ElasticsearchConfig {

    @Value("${elasticsearch.schema:http}")
    private String schema;

    @Value("${elasticsearch.nodes}")
    private String nodes;

    @Value("${elasticsearch.connect-timeout-ms:5000}")
    private int connectTimeoutMs;

    @Value("${elasticsearch.socket-timeout-ms:10000}")
    private int socketTimeoutMs;

    @Value("${elasticsearch.connection-request-timeout-ms:5000}")
    private int connectionRequestTimeoutMs;

    @Value("${elasticsearch.max-connect-total:100}")
    private int maxConnectTotal;

    @Value("${elasticsearch.max-connect-per-route:100}")
    private int maxConnectPerRoute;

    @Bean(destroyMethod = "close")
    public RestHighLevelClient restHighLevelClient() {
        // 拆分地址
        List<HttpHost> hostLists = new ArrayList<>();
        String[] hostList = nodes.split(",");
        for (String addr : hostList) {
            String host = addr.split(":")[0];
            String port = addr.split(":")[1];
            hostLists.add(new HttpHost(host, Integer.parseInt(port), schema));
        }
        HttpHost[] httpHost = hostLists.toArray(new HttpHost[]{});

        // 构建连接对象
        RestClientBuilder builder = RestClient.builder(httpHost);
        // 异步连接延时配置
        builder.setRequestConfigCallback(requestConfigBuilder -> {
            requestConfigBuilder.setConnectTimeout(connectTimeoutMs);
            requestConfigBuilder.setSocketTimeout(socketTimeoutMs);
            requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeoutMs);
            return requestConfigBuilder;
        });
        // 异步连接数配置
        builder.setHttpClientConfigCallback(httpClientBuilder -> {
            httpClientBuilder.setMaxConnTotal(maxConnectTotal);
            httpClientBuilder.setMaxConnPerRoute(maxConnectPerRoute);
            return httpClientBuilder;
        });
        return new RestHighLevelClient(builder);
    }
}

定义ES文档对象

public class ElasticsearchDocument<T> {
    private String id;
    private T data;
    // getter and setter
}

ES常用操作

@Service
public class ElasticsearchServiceImpl implements ElasticsearchService {

    private static final Logger logger = LoggerFactory.getLogger(ElasticsearchServiceImpl.class);

    private static final int DEFAULT_SHARDS = 1;

    private static final int DEFAULT_REPLICAS = 1;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Override
    public void createIndex(String indexName, Map<String, Map<String, Object>> properties) {
        try {
            XContentBuilder mapping = XContentFactory.jsonBuilder();
            mapping.startObject()
                    .startObject("mappings")
                    .field("properties", properties)
                    .endObject()
                    .startObject("settings")
                    .field("number_of_shards", DEFAULT_SHARDS)
                    .field("number_of_replicas", DEFAULT_REPLICAS)
                    .endObject()
                    .endObject();
            CreateIndexRequest request = new CreateIndexRequest(indexName).source(mapping);
            CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
            boolean isCreated = response.isAcknowledged();
            logger.info("索引 {} 创建{}", indexName, isCreated ? "成功" : "失败");
        } catch (IOException e) {
            logger.error(e.getMessage());
        }
    }

    @Override
    public void deleteIndex(String indexName) {
        try {
            DeleteIndexRequest request = new DeleteIndexRequest(indexName);
            boolean isDeleted = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT).isAcknowledged();
            logger.info("索引 {} 删除{}", indexName, isDeleted ? "成功" : "失败");
        } catch (IOException e) {
            logger.error(e.getMessage());
        }
    }

    @Override
    public void save(String indexName, ElasticsearchDocument<?> document) {
        IndexRequest request = new IndexRequest(indexName)
                .id(document.getId())
                .source(JSON.toJSONString(document.getData()), XContentType.JSON);
        try {
            restHighLevelClient.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            logger.error(e.getMessage());
        }
    }

    @Override
    public <T> void save(String indexName, List<ElasticsearchDocument<T>> documentList) {
        // 批量请求
        BulkRequest bulkRequest = new BulkRequest();
        documentList.forEach(doc -> {
            bulkRequest.add(new IndexRequest(indexName)
                    .id(doc.getId())
                    .source(JSON.toJSONString(doc.getData()), XContentType.JSON));
        });

        try {
            restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            logger.error(e.getMessage());
        }
    }

    @Override
    public void deleteDocument(String indexName, String id) {
        DeleteRequest deleteRequest = new DeleteRequest(indexName, id);
        try {
            restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            logger.error(e.getMessage());
        }
    }
}

测试

public class UserDetail {
    private String username;
    private String nickname;
    private Integer age;
    private String address;
    private Long createTime;
    // getter and setter
}
@SpringBootTest
public class ElasticsearchServiceTest {

    @Autowired
    private ElasticsearchService elasticsearchService;

    private final String INDEX_NAME = "user_detail";

    @Test
    public void createIndex() throws IOException {
        Map<String, Object> chineseMap = new HashMap<>(3);
        chineseMap.put("type", "text");
        chineseMap.put("analyzer", "ik_max_word");
        chineseMap.put("search_analyzer", "ik_max_word");

        Map<String, Object> integerMap = new HashMap<>(1);
        integerMap.put("type", "integer");

        Map<String, Object> longMap = new HashMap<>(1);
        longMap.put("type", "long");

        Map<String, Map<String, Object>> properties = new HashMap<>(5);
        properties.put("username", chineseMap);
        properties.put("nickname", chineseMap);
        properties.put("age", integerMap);
        properties.put("address", chineseMap);
        properties.put("createTime", longMap);

        elasticsearchService.createIndex(INDEX_NAME, properties);
    }

    @Test
    public void deleteIndex() {
        elasticsearchService.deleteIndex(INDEX_NAME);
    }

    @Test
    public void save() {
        UserDetail userDetail = new UserDetail("张一", "章亿", 18, "北京", new Date().getTime());
        elasticsearchService.save(INDEX_NAME, new ElasticsearchDocument<>(UUID.randomUUID().toString(), userDetail));
    }

    @Test
    public void saveAll() {
        List<ElasticsearchDocument<UserDetail>> documentList = new ArrayList<>(5);
        UserDetail userDetail1 = new UserDetail("王二", "忘耳", 20, "上海", new Date().getTime());
        UserDetail userDetail2 = new UserDetail("张三", "丈叁", 22, "广州", new Date().getTime());
        UserDetail userDetail3 = new UserDetail("李四", "丽丝", 24, "深圳", new Date().getTime());
        documentList.add(new ElasticsearchDocument<>(UUID.randomUUID().toString(), userDetail1));
        documentList.add(new ElasticsearchDocument<>(UUID.randomUUID().toString(), userDetail2));
        documentList.add(new ElasticsearchDocument<>(UUID.randomUUID().toString(), userDetail3));

        elasticsearchService.save(INDEX_NAME, documentList);
    }

    @Test
    public void delete() {
        elasticsearchService.deleteDocument(INDEX_NAME, "743a6866-c491-4502-b1ec-ad3da3ea2132");
    }
}

测试查询和分页

@SpringBootTest
public class UserDetailTest {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    private final String INDEX_NAME = "user_detail";

    /**
     * 范围查询
     */
    @Test
    public void range() {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.rangeQuery("age").gte(20).lte(25));

        this.getUserDetailResult(searchSourceBuilder);
    }

    /**
     * 布尔查询
     */
    @Test
    public void bool() {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.matchQuery("username", "三")).filter(QueryBuilders.rangeQuery("age").gte(20).lte(25));

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(boolQueryBuilder);

        this.getUserDetailResult(searchSourceBuilder);
    }

    /**
     * 简单查询字符串
     */
    @Test
    public void simpleQueryString() {
        Map<String, Float> filedMap = new HashMap<>(3);
        filedMap.put("username", 0.3f);
        filedMap.put("nickname", 0.2f);
        filedMap.put("address", 0.1f);

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.filter(QueryBuilders.simpleQueryStringQuery("张").fields(filedMap).defaultOperator(Operator.OR));

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(boolQueryBuilder);

        this.getUserDetailResult(searchSourceBuilder);
    }

    private void getUserDetailResult(SearchSourceBuilder searchSourceBuilder) {
        SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = null;
        try {
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (RestStatus.OK.equals(searchResponse.status())) {
            SearchHits hits = searchResponse.getHits();
            for (SearchHit hit : hits) {
                UserDetail userInfo = JSON.parseObject(hit.getSourceAsString(), UserDetail.class);
                System.out.println(userInfo.toString());
            }
        }
    }

    /**
     * 年龄平均值
     */
    @Test
    public void avg() {
        try {
            AggregationBuilder aggregationBuilder = AggregationBuilders.avg("age_avg").field("age");

            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.aggregation(aggregationBuilder);

            SearchRequest request = new SearchRequest(INDEX_NAME);
            request.source(searchSourceBuilder);

            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);

            Aggregations aggregations = response.getAggregations();
            if (RestStatus.OK.equals(response.status()) || aggregations != null) {
                ParsedAvg parsedAvg = aggregations.get("age_avg");
                System.out.println(parsedAvg.getValue());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * from size 分页
     */
    @Test
    public void pageByFromSize() {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery()).from(0).size(2);

        this.getUserDetailResult(searchSourceBuilder);
    }

    /**
     * scroll 分页
     */
    @Test
    public void pageByScroll() {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery()).size(2);

        SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
        searchRequest.source(searchSourceBuilder).scroll(TimeValue.timeValueMinutes(1L));

        SearchResponse searchResponse = null;
        try {
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            System.out.println("scroll_id:" + searchResponse.getScrollId());
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (RestStatus.OK.equals(searchResponse.status())) {
            SearchHits hits = searchResponse.getHits();
            for (SearchHit hit : hits) {
                UserDetail userInfo = JSON.parseObject(hit.getSourceAsString(), UserDetail.class);
                System.out.println(userInfo.toString());
            }
        }

    }

    /**
     * 根据scroll_id查询
     */
    @Test
    public void pageByScrollId() {
        String scrollId = "...";
        SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
        SearchResponse searchResponse = null;
        try {
            searchResponse = restHighLevelClient.scroll(scrollRequest, RequestOptions.DEFAULT);
            System.out.println("scroll_id" + searchResponse.getScrollId());
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (RestStatus.OK.equals(searchResponse.status())) {
            SearchHits hits = searchResponse.getHits();
            for (SearchHit hit : hits) {
                UserDetail userInfo = JSON.parseObject(hit.getSourceAsString(), UserDetail.class);
                System.out.println(userInfo.toString());
            }
        }
    }

	/**
     * 清除scroll_id
     */
    @Test
    public void clearScrollId() {
        String scrollId = "...";
        ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
        clearScrollRequest.addScrollId(scrollId);

        ClearScrollResponse clearScrollResponse = null;
        try {
            clearScrollResponse = restHighLevelClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
            System.out.println(clearScrollResponse.isSucceeded());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * search_after 分页
     */
    @Test
    public void pageBySearchAfter() {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery()).size(2).sort("_id", SortOrder.ASC);

        SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = null;
        try {
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (RestStatus.OK.equals(searchResponse.status())) {
            SearchHits hits = searchResponse.getHits();
            for (SearchHit hit : hits) {
                UserDetail userInfo = JSON.parseObject(hit.getSourceAsString(), UserDetail.class);
                System.out.println(userInfo.toString());
                System.out.println("sort:" + hit.getSortValues()[0]);
            }
        }
    }

    /**
     * 根据最后一条sort值查询
     */
    @Test
    public void pageBySearchAfter2() {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery()).size(2).sort("_id", SortOrder.ASC).searchAfter(new Object[]{"..."});

        SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = null;
        try {
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (RestStatus.OK.equals(searchResponse.status())) {
            SearchHits hits = searchResponse.getHits();
            for (SearchHit hit : hits) {
                UserDetail userInfo = JSON.parseObject(hit.getSourceAsString(), UserDetail.class);
                System.out.println(userInfo.toString());
                System.out.println("sort:" + hit.getSortValues()[0]);
            }
        }
    }
}

2. Spring Data Elasticsearch

添加依赖

<dependencies>
   <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        <version>2.3.4.RELEASE</version>
    </dependency>
</dependencies>

添加配置

spring:
  elasticsearch:
    rest:
      uris: http://localhost:9200

定义User类,映射ES的索引

@Document(indexName = "user")
public class User {
    @Id
    private String id;

    @Field(type = FieldType.Text, searchAnalyzer = "ik_max_word", analyzer = "ik_max_word")
    private String username;
    @Field(type = FieldType.Text, searchAnalyzer = "ik_max_word", analyzer = "ik_max_word")
    private String nickname;
    @Field(type = FieldType.Integer)
    private Integer age;
    @Field(type = FieldType.Text, searchAnalyzer = "ik_max_word", analyzer = "ik_max_word")
    private String address;
    @Field(type = FieldType.Long)
    private Date createTime;
    // getter and setter
}    

@Document:类级别,映射到索引,默认会自动创建索引。
@Id:字段级别,标识id。
@Field:字段级别,定义字段的属性:

  1. name:字段名称,如果未设置,则使用字段名称。
  2. type:字段类型
  3. analyzer,searchAnalyzer,normalizer:指定自定义analyzers 和 normalizer。

定义UserRepository

public interface UserRepository extends ElasticsearchRepository<User, String> {
    List<User> findByUsername(String username);
    List<User> findByAgeBetween(Integer startAge, Integer endAge);
    Page<User> findAll(Pageable pageable);
}

测试

@SpringBootTest
public class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    private final String INDEX_NAME = "user";

    @Test
    public void insert() {
        User user = new User("张五", "张五昵称", 30, "五五路5号", new Date());
        userRepository.save(user);
    }

    @Test
    public void search() {
        List<User> userList = userRepository.findByUsername("三");
        System.out.println(userList);
    }

    @Test
    public void update() {
        List<User> userList = userRepository.findByUsername("张一");
        userList.forEach(user -> {
            user.setUsername(user.getUsername() + "更新");
        });
        userRepository.saveAll(userList);
    }

    @Test
    public void delete() {
        List<User> userList = userRepository.findByUsername("张一");
        userRepository.deleteAll(userList);
    }
	
	/**
     * 范围查询
     */
    @Test
    public void findByAgeBetween() {
        List<User> userList = userRepository.findByAgeBetween(20, 25);
        System.out.println(userList);
    }
	
	/**
     * from size 分页
     */
    @Test
    public void pageByFormSize() {
        Pageable pageable = PageRequest.of(0, 2);
        Page<User> userPage = userRepository.findAll(pageable);
        System.out.println(userPage.getContent());
    }

	/**
     * scroll 分页
     */
    @Test
    public void pageByScroll() {
        IndexCoordinates index = IndexCoordinates.of(INDEX_NAME);

        Query query = new NativeSearchQueryBuilder()
                .withQuery(matchAllQuery())
                .withPageable(PageRequest.of(0, 2))
                .build();

        SearchScrollHits<User> searchScrollHits = elasticsearchRestTemplate.searchScrollStart(6000, query, User.class, index);
        System.out.println("scroll_id:" + searchScrollHits.getScrollId());
        searchScrollHits.get().forEach(searchHit -> {
            System.out.println(searchHit.getContent());
        });
    }

	/**
     * 根据 scroll_id 查询
     */
    @Test
    public void pageByScrollId() {
        IndexCoordinates index = IndexCoordinates.of(INDEX_NAME);

        String scrollId = "...";
        SearchScrollHits<User> searchScrollHits = elasticsearchRestTemplate.searchScrollContinue(scrollId, 6000, User.class, index);

        System.out.println("scroll_id:" + searchScrollHits.getScrollId());

        searchScrollHits.get().forEach(searchHit -> {
            System.out.println(searchHit.getContent());
        });
    }
}

参考:
ES 官方文档
Spring Boot 集成 ElasticSearch (7.x 版本)搜索引擎
SpringBoot 操作 ElasticSearch 详解(万字长文)
Spring Data Elasticsearch 官方文档
Spring Boot 集成 Elasticsearch 实战

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值