一、前言

上一篇我们通过kibana的可视化界面,对es的索引以及文档的常用操作做了毕竟详细的总结,本篇将介绍如何使用java完成对es的操作,这也是实际开发中将要涉及到的。

二、java操作es的常用模式

目前,开发中使用java操作es,不管是框架集成,还是纯粹的使用es的api,主要通过下面两种方式:

  • rest-api,主流的像RestHighLevelClient ;

  • 与springboot集成时的jpa操作,主要是ElasticsearchRepository 相关的api;

上面两种模式的api在开发中都可以方便的使用,相比之下,RestHighLevelClient相关的api灵活性更高,而ElasticsearchRepository 底层做了较多的封装,学习和使用的成本更低,上手更快。

接下来将对上面的两种操作模式做一个详细的总结,本篇所述的es基于7.6.2版本,配合的kibana也为7.6.2版本。

三、rest-api 操作

1、前置准备

导入依赖

导入核心依赖,主要是es的rest依赖,其他的可以根据自己的需要导入;

                    org.apache.logging.log4j            log4j-api            2.11.2                            org.apache.logging.log4j            log4j-core            2.11.2                            org.apache.logging.log4j            log4j-core            2.8.2                            org.apache.logging.log4j            log4j-jcl            2.11.2                            commons-logging            commons-logging            1.2                            org.elasticsearch            elasticsearch            7.6.2                            org.elasticsearch.client            elasticsearch-rest-high-level-client            7.6.2                            com.fasterxml.jackson.core            jackson-databind            2.9.9                            junit            junit            4.12            

es连接测试

为了确保后续的所有实验能够正常进行,建议先通过下面的程序测试下是否能够连接es服务;

import org.apache.http.HttpHost;import org.elasticsearch.client.RestClient;import org.elasticsearch.client.RestHighLevelClient;import java.io.IOException;public class EsClientTest {    public static void main(String[] args) throws IOException {        RestHighLevelClient esClient = new RestHighLevelClient(                RestClient.builder(new HttpHost("IP",9200,"http"))        );        System.out.println("success");        esClient.close();    }}

运行上面的代码,出现下面的效果说明连接成功

2、索引相关操作api的使用

为了减少连接相关的编码,我们将es的client提出到全局的静态变量中,其他方法中就可以直接引用了

    public static RestHighLevelClient esClient;    static {        esClient = new RestHighLevelClient(                RestClient.builder(new HttpHost("IP", 9200, "http"))        );    }

2.1 创建索引

    /**     * 创建索引     * @throws IOException     */    public static void createIndex() throws IOException {        CreateIndexRequest createIndexRequest = new CreateIndexRequest("user");        CreateIndexResponse indexResponse = esClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);        boolean acknowledged = indexResponse.isAcknowledged();        System.out.println("索引创建状态:" + acknowledged);    }

main方法中调用方法即可

public static void main(String[] args) throws IOException {        System.out.println("connect success");        createIndex();        esClient.close();}

运行main创建索引

通过kibana查询确认索引是否创建成功

2.2 获取索引

/**     * 索引信息查询     * @throws IOException     */    public static void getIndex() throws IOException {        GetIndexRequest getIndexRequest = new GetIndexRequest("user");        GetIndexResponse getIndexResponse = esClient.indices().get(getIndexRequest, RequestOptions.DEFAULT);        System.out.println(getIndexResponse.getAliases());        System.out.println(getIndexResponse.getMappings());        System.out.println(getIndexResponse.getSettings());    }

2.3 删除索引

    /**     * 删除索引     * @throws IOException     */    public static void deleteIndex() throws IOException {        DeleteIndexRequest getIndexRequest = new DeleteIndexRequest("user");        AcknowledgedResponse delete = esClient.indices().delete(getIndexRequest, RequestOptions.DEFAULT);        System.out.println("索引删除状态:" + delete.isAcknowledged());    }

3、文档常用操作api的使用

在实际开发过程中,对于文档的操作更为的频繁,接下来演示与es文档相关的操作api。

前置准备

public static ObjectMapper objectMapper = new ObjectMapper();    public static RestHighLevelClient esClient;    static {        esClient = new RestHighLevelClient(                RestClient.builder(new HttpHost("IP", 9200, "http"))        );    }

用于测试使用的对象

public class User {    private String name;    private String sex;    private Integer age;    private Integer salary;    public User() {    }    public User(String name, String sex, Integer age, Integer salary) {        this.name = name;        this.sex = sex;        this.age = age;        this.salary = salary;    }    public Integer getSalary() {        return salary;    }    public void setSalary(Integer salary) {        this.salary = salary;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getSex() {        return sex;    }    public void setSex(String sex) {        this.sex = sex;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }}

3.1 索引添加文档

注意:实际开发中,user对象应该作为参数传入【可以基于此做进一步的封装】

    /**     * 添加数据     * @throws Exception     */    public static void add() throws Exception{        IndexRequest indexRequest = new IndexRequest();        indexRequest.index("user").id("1008");        User user = new User();        user.setName("孙二娘");        user.setAge(23);        user.setSex("女");        user.setSalary(7000);        String userData = objectMapper.writeValueAsString(user);        indexRequest.source(userData,XContentType.JSON);        //插入数据        IndexResponse response = esClient.index(indexRequest, RequestOptions.DEFAULT);        System.out.println(response.status());        System.out.println(response.getResult());    }

在main方法调用执行下该方法

public static void main(String[] args) throws Exception {        add();        esClient.close();}

可以通过kibana查询检查下数据是否添加成功

3.2 修改文档

    /**     * 修改数据     * @throws Exception     */    public static void update() throws Exception{        UpdateRequest request = new UpdateRequest();        request.index("user").id("1008");        request.doc(XContentType.JSON,"name","母夜叉");        //插入数据        UpdateResponse response = esClient.update(request, RequestOptions.DEFAULT);        System.out.println(response.getResult());    }

3.3 删除文档

    /**     * 删除     * @throws Exception     */    public static void delete() throws Exception{        DeleteRequest request = new DeleteRequest();        request.index("user").id("1008");        //插入数据        DeleteResponse delete = esClient.delete(request, RequestOptions.DEFAULT);        System.out.println(delete.getResult());    }

3.4 批量添加文档

有些情况下,单条插入效率太低,可以使用es的批量插入功能一次性添加多条数据

    /**     * 批量添加     * @throws Exception     */    public static void batchInsert() throws Exception{        BulkRequest bulkRequest = new BulkRequest();        User user1 = new User("关羽","男",33,5500);        String userData1 = objectMapper.writeValueAsString(user1);        IndexRequest indexRequest1 = new IndexRequest().index("user").id("1002").source(userData1, XContentType.JSON);        bulkRequest.add(indexRequest1);        User user2 = new User("黄忠","男",50,8000);        String userData2 = objectMapper.writeValueAsString(user2);        IndexRequest indexRequest2 = new IndexRequest().index("user").id("1003").source(userData2, XContentType.JSON);        bulkRequest.add(indexRequest2);        User user3 = new User("黄忠2","男",49,10000);        String userData3 = objectMapper.writeValueAsString(user3);        IndexRequest indexRequest3 = new IndexRequest().index("user").id("1004").source(userData3, XContentType.JSON);        bulkRequest.add(indexRequest3);        User user4 = new User("赵云","男",33,12000);        String userData4 = objectMapper.writeValueAsString(user4);        IndexRequest indexRequest4 = new IndexRequest().index("user").id("1005").source(userData4, XContentType.JSON);        bulkRequest.add(indexRequest4);        User user5 = new User("马超","男",38,20000);        String userData5 = objectMapper.writeValueAsString(user5);        IndexRequest indexRequest5 = new IndexRequest().index("user").id("1006").source(userData5, XContentType.JSON);        bulkRequest.add(indexRequest5);        User user6 = new User("关羽","男",41,27000);        String userData6 = objectMapper.writeValueAsString(user6);        IndexRequest indexRequest6 = new IndexRequest().index("user").id("1007").source(userData6, XContentType.JSON);        bulkRequest.add(indexRequest6);        BulkResponse bulkResponse = esClient.bulk(bulkRequest, RequestOptions.DEFAULT);        System.out.println(bulkResponse.status());        System.out.println(bulkResponse.getItems());    }

3.5 批量删除

可以通过批量操作一次性删除多条数据

    /**     * 批量删除     * @throws Exception     */    public static void batchDelete() throws Exception{        BulkRequest bulkRequest = new BulkRequest();        DeleteRequest indexRequest1 = new DeleteRequest().index("user").id("1002");        DeleteRequest indexRequest2 = new DeleteRequest().index("user").id("1003");        DeleteRequest indexRequest3 = new DeleteRequest().index("user").id("1004");        DeleteRequest indexRequest4 = new DeleteRequest().index("user").id("1005");        DeleteRequest indexRequest5 = new DeleteRequest().index("user").id("1006");        DeleteRequest indexRequest6 = new DeleteRequest().index("user").id("1007");        bulkRequest.add(indexRequest1);        bulkRequest.add(indexRequest2);        bulkRequest.add(indexRequest3);        bulkRequest.add(indexRequest4);        bulkRequest.add(indexRequest5);        bulkRequest.add(indexRequest6);        BulkResponse bulkResponse = esClient.bulk(bulkRequest, RequestOptions.DEFAULT);        System.out.println(bulkResponse.status());        System.out.println(bulkResponse.getItems());    }

4、文档搜索相关api的使用

我们知道es最强大的功能就是文档检索了,接下来演示下与es文档查询相关的常用API的操作;

4.1 查询某个索引下的所有数据

    /**     * 查询某个索引下的所有数据     * @throws Exception     */    public static void searchIndexAll() throws Exception{        SearchRequest request = new SearchRequest();        request.indices("user");        // 索引中的全部数据查询        SearchSourceBuilder query = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());        request.source(query);        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);        SearchHits hits = response.getHits();        for (SearchHit searchHit : hits){            System.out.println(searchHit.getSourceAsString());        }    }

执行一下对该方法的调用

这个效果和在kibana中下面的操作效果是一样的

4.2 批量查询多条数据

针对那种需要一次性查出多条数据的场景可以考虑使用

        MultiGetRequest multiGetRequest = new MultiGetRequest();        multiGetRequest.add("user", "1002");        multiGetRequest.add("user", "1003");        MultiGetResponse responses = esClient                .mget(multiGetRequest, RequestOptions.DEFAULT);        Iterator iterator = responses.iterator();        while (iterator.hasNext()){            MultiGetItemResponse next = iterator.next();            System.out.println(next.getResponse().getSourceAsString());        }

4.3 根据条件精准查询

根据性别查询,有点类似于mysql 中的 where sex=’女’ 这样的效果

        TermQueryBuilder ageQueryBuilder = QueryBuilders.termQuery("sex", "女");        SearchSourceBuilder query = new SearchSourceBuilder().query(ageQueryBuilder);        request.source(query);        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);        System.out.println(response.getHits().getHits());        System.out.println(response.getHits().getTotalHits());        SearchHits hits = response.getHits();        for (SearchHit searchHit : hits){            System.out.println(searchHit.getSourceAsString());        }

4.4 分页查询

考察from + size的使用

        SearchSourceBuilder sourceBuilder = new                                 SearchSourceBuilder().query(QueryBuilders.matchAllQuery());        sourceBuilder.from(0).size(3);        request.source(sourceBuilder);        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);        System.out.println(response.getHits().getHits());        System.out.println(response.getHits().getTotalHits());        SearchHits hits = response.getHits();        for (SearchHit searchHit : hits){            System.out.println(searchHit.getSourceAsString());        }

4.5 查询结果按照某个字段进行排序

将查询结果按照age进行排序

        SearchSourceBuilder sourceBuilder = new             SearchSourceBuilder().query(QueryBuilders.matchAllQuery());        sourceBuilder.sort("age",SortOrder.ASC);        request.source(sourceBuilder);        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);        System.out.println(response.getHits().getHits());        System.out.println(response.getHits().getTotalHits());        SearchHits hits = response.getHits();        for (SearchHit searchHit : hits){            System.out.println(searchHit.getSourceAsString());        }

4.6 查询结果过滤某些字段

类似于mysql中只查询某个表的部分字段

        SearchSourceBuilder sourceBuilder = new                 SearchSourceBuilder().query(QueryBuilders.matchAllQuery());        request.source(sourceBuilder);        String[] includes = {"name","sex"};        String[] excludes = {"age"};        sourceBuilder.fetchSource(includes,excludes);        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);        System.out.println(response.getHits().getHits());        System.out.println(response.getHits().getTotalHits());        SearchHits hits = response.getHits();        for (SearchHit searchHit : hits){            System.out.println(searchHit.getSourceAsString());        }

4.7 多条件查询

es可以像mysql那样组合多个条件进行查询,考察对BoolQuery的使用,如下:查询性别为难男,年龄在35到45之间的用户;

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();        boolQueryBuilder.must(QueryBuilders.matchQuery("sex","男"));        boolQueryBuilder.must(QueryBuilders.rangeQuery("age").lt(45).gt(35));        sourceBuilder.query(boolQueryBuilder);        request.source(sourceBuilder);        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);        System.out.println(response.getHits().getHits());        System.out.println(response.getHits().getTotalHits());        SearchHits hits = response.getHits();        for (SearchHit searchHit : hits){            System.out.println(searchHit.getSourceAsString());        }

4.8 范围查询

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();        RangeQueryBuilder rangeQueryBuilder =             QueryBuilders.rangeQuery("age").gte(35).lte(45);        sourceBuilder.query(rangeQueryBuilder);        request.source(sourceBuilder);        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);        System.out.println(response.getHits().getHits());        System.out.println(response.getHits().getTotalHits());        SearchHits hits = response.getHits();        for (SearchHit searchHit : hits){            System.out.println(searchHit.getSourceAsString());        }

4.9 模糊查询

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();        FuzzyQueryBuilder fuzzyQueryBuilder =                QueryBuilders.fuzzyQuery("name", "黄忠")                        .fuzziness(Fuzziness.ONE);        sourceBuilder.query(fuzzyQueryBuilder);        request.source(sourceBuilder);        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);        System.out.println(response.getHits().getHits());        System.out.println(response.getHits().getTotalHits());        SearchHits hits = response.getHits();        for (SearchHit searchHit : hits){            System.out.println(searchHit.getSourceAsString());        }

4.10 高亮查询

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();        TermQueryBuilder ageQueryBuilder = QueryBuilders.termQuery("age", 33);        HighlightBuilder highlightBuilder = new HighlightBuilder();        highlightBuilder.preTags("");        highlightBuilder.postTags("");        highlightBuilder.field("name");        sourceBuilder.highlighter(highlightBuilder);        sourceBuilder.query(ageQueryBuilder);        request.source(sourceBuilder);        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);        System.out.println(response.getHits().getHits());        System.out.println(response.getHits().getTotalHits());        SearchHits hits = response.getHits();        for (SearchHit searchHit : hits){            System.out.println(searchHit.getSourceAsString());        }

4.11 多字段查询multi_match

这个用法表示从多个字段中匹配某个关键字

        SearchSourceBuilder builder = new SearchSourceBuilder();        MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery("黄忠","name", "sex");        multiMatchQuery.operator(Operator.OR);        builder.query(multiMatchQuery);        request.source(builder);        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);        System.out.println(response.getHits().getHits());        System.out.println(response.getHits().getTotalHits());        SearchHits hits = response.getHits();        for (SearchHit searchHit : hits){            System.out.println(searchHit.getSourceAsString());        }

4.12 聚合查询

        SearchSourceBuilder builder = new SearchSourceBuilder();        AggregationBuilder aggregationBuilder = AggregationBuilders.max("maxAge").field("age");        builder.aggregation(aggregationBuilder);        request.source(builder);        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);        System.out.println(response.getHits().getHits());        System.out.println(response.getHits().getTotalHits());        SearchHits hits = response.getHits();        for (SearchHit searchHit : hits){            System.out.println(searchHit.getSourceAsString());        }

4.13 分组查询

        SearchSourceBuilder builder = new SearchSourceBuilder();        AggregationBuilder aggregationBuilder = AggregationBuilders.terms("ageGroup").field("age");        builder.aggregation(aggregationBuilder);        request.source(builder);        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);        System.out.println(response.getHits().getHits());        System.out.println(response.getHits().getTotalHits());        SearchHits hits = response.getHits();        for (SearchHit searchHit : hits){            System.out.println(searchHit.getSourceAsString());        }

四、与springboot 整合

es提供了与spring,springboot快速整合的第三方SDK,接下来以spring-data为例进行说明;

spring-boot-starter-data-elasticsearch 与spring其他相关的jpa方式使用类似,封装了丰富的API接口,客户只需要继承其提供的接口,就能方便的使用内置的API

前置准备

本地创建一个maven工程

1、导入核心依赖

            org.springframework.boot        spring-boot-starter-parent        2.3.6.RELEASE                                    org.projectlombok            lombok                            org.springframework.boot            spring-boot-starter-data-elasticsearch                            org.springframework.boot            spring-boot-devtools            runtime            true                            org.springframework.boot            spring-boot-starter-test            test                            org.springframework.boot            spring-boot-test                            junit            junit                            org.springframework            spring-test            

2、核心配置文件

# es 服务地址elasticsearch.host=IP# es 服务端口elasticsearch.port=9200# 配置日志级别,开启 debug 日志logging.level.com.congge=debug

整合过程

1、创建一个实体类

该实体类属于连接es文档与客户端的一个中间转换层,使用过jpa或者mybatis-plus的同学对这个应该不陌生;

import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import lombok.ToString;import org.springframework.data.annotation.Id;import org.springframework.data.elasticsearch.annotations.Document;import org.springframework.data.elasticsearch.annotations.Field;import org.springframework.data.elasticsearch.annotations.FieldType;@Data@NoArgsConstructor@AllArgsConstructor@ToString@Document(indexName = "shopping", shards = 3, replicas = 1)public class Product {    //必须有 id,这里的 id 是全局唯一的标识,等同于 es 中的"_id"    @Id    private Long id;//商品唯一标识    /**     * type : 字段数据类型     * analyzer : 分词器类型     * index : 是否索引(默认:true)     * Keyword : 短语,不进行分词     */    @Field(type = FieldType.Text, analyzer = "ik_max_word")    private String title;//商品名称    @Field(type = FieldType.Keyword)    private String category;//分类名称    @Field(type = FieldType.Double)    private Double price;//商品价格    @Field(type = FieldType.Keyword, index = false)    private String images;//图片地址}

2、提供一个接口,继承ElasticsearchRepository

import com.congge.entity.Product;import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;import org.springframework.stereotype.Repository;@Repositorypublic interface ProductDao extends ElasticsearchRepository{}

3、核心配置类

import lombok.Data;import org.apache.http.HttpHost;import org.elasticsearch.client.RestClient;import org.elasticsearch.client.RestClientBuilder;import org.elasticsearch.client.RestHighLevelClient;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Configuration;//import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;@ConfigurationProperties(prefix = "elasticsearch")@Configuration@Datapublic class EsConfig extends com.congge.config.AbstractElasticsearchConfiguration {    private String host ;    private Integer port ;    //重写父类方法    @Override    public RestHighLevelClient elasticsearchClient() {        RestClientBuilder builder = RestClient.builder(new HttpHost(host, port));        RestHighLevelClient restHighLevelClient = new                RestHighLevelClient(builder);        return restHighLevelClient;    }}
import org.elasticsearch.client.RestHighLevelClient;import org.springframework.context.annotation.Bean;import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;import org.springframework.data.elasticsearch.core.ElasticsearchOperations;import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;public abstract class AbstractElasticsearchConfiguration extends ElasticsearchConfigurationSupport {    //需重写本方法    public abstract RestHighLevelClient elasticsearchClient();    @Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })    public ElasticsearchOperations elasticsearchOperations(ElasticsearchConverter elasticsearchConverter) {        return new ElasticsearchRestTemplate(elasticsearchClient(), elasticsearchConverter);    }}

模拟测试

接下来通过junit的方式进行测试

1、索引相关的操作测试

import com.congge.entity.Product;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.data.elasticsearch.core.ElasticsearchRestTemplate;import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)@SpringBootTestpublic class EsIndexTest {    //注入 ElasticsearchRestTemplate    @Autowired    private ElasticsearchRestTemplate elasticsearchRestTemplate;    //创建索引并增加映射配置    @Test    public void createIndex(){        //创建索引,系统初始化会自动创建索引        System.out.println("创建索引");    }    @Test    public void deleteIndex(){        //创建索引,系统初始化会自动创建索引        boolean flg = elasticsearchRestTemplate.deleteIndex(Product.class);        System.out.println("删除索引 = " + flg);    }}

基于spring-data的方式,在工程启动的时候,会自动读取实体类相关的注解,自动完成索引的创建,运行下创建索引的测试方法;

然后去到kibana上面确认下是否创建成功;

2、文档相关的操作测试

该测试类中列举了常用的增删改查操作

import com.congge.dao.ProductDao;import com.congge.entity.Product;import org.elasticsearch.index.query.QueryBuilders;import org.elasticsearch.index.query.TermQueryBuilder;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.data.domain.Page;import org.springframework.data.domain.PageRequest;import org.springframework.data.domain.Sort;import org.springframework.test.context.junit4.SpringRunner;import java.util.ArrayList;import java.util.List;@RunWith(SpringRunner.class)@SpringBootTestpublic class EsDocTest {    @Autowired    private ProductDao productDao;    /**     * 新增     */    @Test    public void save() {        Product product = new Product();        product.setId(2L);        product.setTitle("ipad mini");        product.setCategory("ipad");        product.setPrice(1998.0);        product.setImages("http://ipad.jpg");        productDao.save(product);    }    //修改    @Test    public void update(){        Product product = new Product();        product.setId(2L);        product.setTitle("iphone");        product.setCategory("mobile");        product.setPrice(6999.0);        product.setImages("http://www.phone.jpg");        productDao.save(product);    }    //根据 id 查询    @Test    public void findById(){        Product product = productDao.findById(2L).get();        System.out.println(product);    }    //查询所有    @Test    public void findAll(){        Iterable products = productDao.findAll();        for (Product product : products) {            System.out.println(product);        }    }    //删除    @Test    public void delete(){        Product product = new Product();        product.setId(2L);        productDao.delete(product);    }    //批量新增    @Test    public void saveAll(){        List productList = new ArrayList();        for (int i = 0; i < 10; i++) {            Product product = new Product();            product.setId(Long.valueOf(i));            product.setTitle("iphone" + i);            product.setCategory("mobile");            product.setPrice(5999.0 + i);            product.setImages("http://www.phone.jpg");            productList.add(product);        }        productDao.saveAll(productList);    }    //分页查询    @Test    public void findByPageable(){        //设置排序(排序方式,正序还是倒序,排序的 id)        Sort sort = Sort.by(Sort.Direction.DESC,"id");        int currentPage=0;//当前页,第一页从 0 开始, 1 表示第二页        int pageSize = 5;//每页显示多少条        //设置查询分页        PageRequest pageRequest = PageRequest.of(currentPage, pageSize,sort);        //分页查询        Page productPage = productDao.findAll(pageRequest);        for (Product Product : productPage.getContent()) {            System.out.println(Product);        }    }    /**     * term 查询     * search(termQueryBuilder) 调用搜索方法,参数查询构建器对象     */    @Test    public void termQuery(){        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", "iphone");        Iterable products = productDao.search(termQueryBuilder);        for (Product product : products) {            System.out.println(product);        }    }    /**     * term 查询加分页     */    @Test    public void termQueryByPage(){        int currentPage= 0 ;        int pageSize = 5;        //设置查询分页        PageRequest pageRequest = PageRequest.of(currentPage, pageSize);        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", "phone");        Iterable products =                productDao.search(termQueryBuilder,pageRequest);        for (Product product : products) {            System.out.println(product);        }    }}

测试其中批量新增的方法

更多丰富的API接口的使用有兴趣的同学可以基于此继续深入的研究学习。