Spring Boot Data操作ElasticSearch

1 引入依赖

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-elasticsearchartifactId>
dependency>

2 编写yml配置

  • spring-data(2~3.x版本配置)
spring:
  data:
    elasticsearch:
      cluster-nodes: 172.16.251.142:9300
  • spring-data(新版本推荐配置) RestHighLevelClient rest客户端 ElasticSearchRespositoy接口
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo("192.168.52.128:9200")
                .build();
        return RestClients.create(clientConfiguration).rest();
    }

}

3 RestHighLevelClient操作

3.1 增加索引
@SpringBootTest
public class TestRestClient {

    @Resource
    private RestHighLevelClient restHighLevelClient;

    @Test
    public void addIndex() throws IOException {
        IndexRequest indexRequest = new IndexRequest("ems", "emp", "99");
        indexRequest.source("{\"name\":\"Boot创建的\",\"age\":23}", XContentType.JSON);
        IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        System.out.println(indexResponse.status());
    }
}

3.2 删除索引
    @Test
    public void deleteIndex() throws IOException {
        DeleteRequest deleteRequest = new DeleteRequest("ems", "emp", "99");
        DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
        System.out.println(deleteResponse.status());
    }
3.3 更新文档
    @Test
    public void update() throws IOException {
        UpdateRequest updateRequest = new UpdateRequest("ems", "emp", "99");
        updateRequest.doc("{\"name\":\"Boot创建的\",\"age\":88}",XContentType.JSON);
        UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println(updateResponse.status());
    }
3.4 批量操作
    @Test
    public void bulk() throws IOException {
        BulkRequest bulkRequest = new BulkRequest();

        IndexRequest indexRequest1 = new IndexRequest("ems", "emp", "101");
        indexRequest1.source("{\"name\":\"Boot创建的1\",\"age\":23}", XContentType.JSON);

        IndexRequest indexRequest2 = new IndexRequest("ems", "emp", "102");
        indexRequest2.source("{\"name\":\"Boot创建的2\",\"age\":23}", XContentType.JSON);

        IndexRequest indexRequest3 = new IndexRequest("ems", "emp", "103");
        indexRequest3.source("{\"name\":\"Boot创建的3\",\"age\":23}", XContentType.JSON);

        IndexRequest indexRequest4 = new IndexRequest("ems", "emp", "104");
        indexRequest4.source("{\"name\":\"Boot创建的4\",\"age\":24}", XContentType.JSON);

        UpdateRequest updateRequest = new UpdateRequest("ems", "emp", "103");
        updateRequest.doc("{\"name\":\"Boot创建的被修改\",\"age\":88}",XContentType.JSON);

        DeleteRequest deleteRequest = new DeleteRequest("ems", "emp", "104");

        bulkRequest.add(indexRequest1)
                .add(indexRequest2)
                .add(indexRequest3)
                .add(indexRequest4)
                .add(updateRequest)
                .add(deleteRequest);

        BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);

        BulkItemResponse[] items = bulkResponse.getItems();

        for (BulkItemResponse item : items) {
            System.out.println(item.status());
        }
    }
3.4 查询全部
    @Test
    public void queryAll() throws IOException {
        SearchRequest searchRequest = new SearchRequest("ems");

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        searchSourceBuilder.query(QueryBuilders.matchAllQuery()).size(99);

        searchRequest.types("emp").source(searchSourceBuilder);

        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        SearchHit[] hits = searchResponse.getHits().getHits();

        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());

        }
    }
3.5 复杂查询
    @Test
    public void search() throws IOException {

        SearchRequest searchRequest = new SearchRequest("ems");

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        searchSourceBuilder.query(QueryBuilders.matchAllQuery())
                .from(0)
                .size(11)
                .postFilter(QueryBuilders.matchAllQuery())
                .highlighter(new HighlightBuilder().field("*").requireFieldMatch(false));

        searchRequest.types("emp").source(searchSourceBuilder);

        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("符合条件的文档总数:"+searchResponse.getHits().getTotalHits());
        System.out.println("符合条件的文档最大得分:"+searchResponse.getHits().getMaxScore());

        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());

        }
    }

4 EmpRepository操作

4.1 编写entity
/**
 *      @Document 用在类上
 *      作用:       将Emp的对象映射成ES中一条json格式文档
 *      indexName: 用来指定这个对象的转为json文档存入那个索引中 要求:ES服务器中之前不能存在此索引名
 *      type     : 用来指定在当前这个索引下创建的类型名称
 */

@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "ems",type = "emp")
public class Emp {

    @Id //用来将对象中id属性与文档中_id 一一对应
    private String id;

    // 用在属性上 代表mapping中一个属性 一个字段 type:属性 用来指定字段类型 analyzer:指定分词器
    @Field(type = FieldType.Text,analyzer = "ik_max_word")
    private String name;

    @Field(type = FieldType.Integer)
    private Integer age;

    @Field(type = FieldType.Date)
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date bir;

    @Field(type = FieldType.Text,analyzer = "ik_max_word")
    private String content;

    @Field(type = FieldType.Text,analyzer = "ik_max_word")
    private String address;
}

@Document: 代表一个文档记录

indexName: 用来指定索引名称

type: 用来指定索引类型

@Id: 用来将对象中id和ES中_id映射

@Field: 用来指定ES中的字段对应Mapping

type: 用来指定ES中存储类型

analyzer: 用来指定使用哪种分词器

4.2 编写EmpRepository
//自定义EmpRepository
public interface EmpRepository extends ElasticsearchRepository<Emp,String> {

    //根据姓名查询
    List<Emp> findByName(String name);

    //根据年龄查询
    List<Emp> findByAge(Integer age);

    //根据姓名和地址
    List<Emp> findByNameAndAddressAndAge(String name, String address, Integer age);

    //根据姓名或年龄查询
    List<Emp> findByNameOrAge(String name, Integer age);

    //查询年龄大于等于 8
    List<Emp> findByAgeGreaterThanEqual(Integer value);
    
}
4.3 添加索引或更新文档

NOTE:这种方式根据实体类中中配置自动在ES创建索引,类型以及映射

@SpringBootTest
public class TestEmpRepository {

    @Resource
    private EmpRepository empRepository;

    @Test
    public void save(){
        Emp emp = new Emp();
        emp.setId(UUID.randomUUID().toString());
        emp.setName("西柚仔");
        emp.setAge(18);
        emp.setBir(new Date());
        emp.setContent("他是一个帅哥");
        emp.setAddress("深圳市");

        empRepository.save(emp);
    }
}

4.4 删除一条文档
    @Test
    public void delete(){
        empRepository.deleteById("b6a8bcf3-bd19-4cb7-b6b4-9074e869d771");
    }
4.5 删除所有文档
    @Test
    public void deleteAll(){
        empRepository.deleteAll();
    }
4.6 根据ID查询一条文档
    @Test
    public void findOne(){
        Optional<Emp> optional = empRepository.findById("acf4a5e3-4fee-44d9-9751-e96389264219");
        System.out.println(optional.get());
    }
4.7排序查询所有文档
    @Test
    public void findAll(){
        Iterable<Emp> all = empRepository.findAll(Sort.by(Sort.Order.asc("age")));
        all.forEach(emp -> System.out.println(emp));
    }
4.8 分页查询所有文档
    @Test
    public void findPage(){
        Page<Emp> search = empRepository.search(QueryBuilders.matchAllQuery(), PageRequest.of(1, 5));
        search.forEach(emp -> System.out.println(emp));
    }
4.9 自定义基本查询
Keyword Sample Elasticsearch Query String
And findByNameAndPrice {"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
Or findByNameOrPrice {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
Is findByName {"bool" : {"must" : {"field" : {"name" : "?"}}}}
Not findByNameNot {"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
Between findByPriceBetween {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
LessThanEqual findByPriceLessThan {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
GreaterThanEqual findByPriceGreaterThan {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
Before findByPriceBefore {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
After findByPriceAfter {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
Like findByNameLike {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
StartingWith findByNameStartingWith {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
EndingWith findByNameEndingWith {"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}
Contains/Containing findByNameContaining {"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}}
In findByNameIn
(Collectionnames)
{"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}
NotIn findByNameNotIn
(Collectionnames)
{"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}
Near findByStoreNear Not Supported Yet !
True findByAvailableTrue {"bool" : {"must" : {"field" : {"available" : true}}}}
False findByAvailableFalse {"bool" : {"must" : {"field" : {"available" : false}}}}
OrderBy findByAvailable
TrueOrderByNameDesc
{"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}
    @Test
    public void FindCustomize(){
        List<Emp> empList = empRepository.findByName("西柚仔");
        empList.forEach(emp -> System.out.println(emp));

        System.out.println("#################");

        List<Emp> empList1 = empRepository.findByAge(23);
        empList1.forEach(emp -> System.out.println(emp));

        System.out.println("#################");

        List<Emp> empList2 = empRepository.findByNameAndAddressAndAge("西柚仔", "深圳市", 18);
        empList2.forEach(emp -> System.out.println(emp));

        System.out.println("#################");

        List<Emp> empList3 = empRepository.findByNameOrAge("不知名", 18);
        empList3.forEach(emp -> System.out.println(emp));

        System.out.println("#################");

        List<Emp> empList4 = empRepository.findByAgeGreaterThanEqual(59);
        empList4.forEach(emp -> System.out.println(emp));
    }

5 实现复杂查询

5.1 分页查询并排序
    @Test
    public void searchPageAndSort() throws IOException {
        SearchRequest searchRequest = new SearchRequest();

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        searchSourceBuilder.from(0).size(3)
                .sort("age", SortOrder.ASC)
                .query(QueryBuilders.matchAllQuery());

        searchRequest.indices("ems").types("emp").source(searchSourceBuilder);

        SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());

        }
    }
5.2 高亮查询
    @Test
    public void searchHighlight() throws IOException {

        SearchRequest searchRequest = new SearchRequest();

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        HighlightBuilder highlightBuilder = new HighlightBuilder();

        highlightBuilder.field("content")
                .requireFieldMatch(false)
                .preTags("")
                .postTags("");

        searchSourceBuilder.from(0).size(3)
                .sort("age", SortOrder.ASC)
                .query(QueryBuilders.termQuery("content","框架"))
                .highlighter(highlightBuilder);

        searchRequest.indices("ems").types("emp").source(searchSourceBuilder);

        SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        SearchHit[] hits = search.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());

            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            highlightFields.forEach((k,v)-> System.out.println("key: "+k+" value: "+v.fragments()[0]));
        }
    }

你可能感兴趣的:(ElasticSearch)