使用 Spring-Data-ElasticSearch操作ES

文章目录

  • Spring-Data-elastic search
      • 使用Spring Data Repositories
          • 使用Repositoriy的方法
          • 实体类:
      • ElasticSearch操作:
          • 插入document:
          • 查询document:
      • 自定义查询:
          • 根据方法名创建查询:
          • 使用 @Query来创建查询
      • 高亮显示:
      • 聚合操作
    • 分页查询:
  • 代码

今天在学 尚硅谷的 ES教程的时候,发现在使用 Spring data elasticsearch来操作ES的时候,讲的内容比较少,所以我就去官网学习了一下Spring-data-elasticsearch。
所有代码在最后

Spring-Data-elastic search

使用Spring Data Repositories

spring data的中心接口是 Repository ,需要实体类和ID作为类型参数,这个CrudRepository 接口为我们正在管理的实体类提供复杂的CRUD功能

PagingAndSortingRepository则是继承了 CrudRepository接口,还增加了额外的方法来简化对实体的分页访问

分页接口的使用:

PagingAndSortingRepository<User, Long> repository = // … get access to a bean
Page<User> users = repository.findAll(PageRequest.of(1, 20));
使用Repositoriy的方法
  1. 声明一个接口,继承Repositoriy接口:

    interface PersonRepository extends Repository<Person, Long> {}
    
  2. 在接口上声明查询方法,也可以不声明

    interface PersonRepository extends Repository<Person, Long> {
      List<Person> findByLastname(String lastname);
    }
    
  3. 对接口使用 @Repositories,为接口创建代理实例

  4. 自动注入@AutoWired 接口并使用

实体类:

实体类作为ES的映射对象,需要对该类添加注解:

  • @Document: 应用于类级别,表示该类是映射到数据库的候选。最重要的属性是:
    • indexName:存储该实体的索引名称
    • shards:索引的分片数。
    • replicas:索引的副本数。
    • createIndex: 配置是否在使用 Repositories时创建索引。默认值为*true*。
    • versionType: 版本管理的配置。默认值为EXTERNAL
  • @Id:在字段级别应用以标记用于标识目的的字段。
  • @Field:应用于字段级别,定义字段的属性
    • name: 字段名称,因为它将在 Elasticsearch 文档中表示,如果未设置,则使用 Java 字段名称。
    • type:字段类型,可以是Text、Keyword、Long、Integer、Short、Byte、Double、Float等等,
    • formatDate类型的pattern定义。必须在日期类型上定义。format
    • store: 标记原始字段值是否应存储在 Elasticsearch 中,默认值为false
    • analyzer, searchAnalyzer,normalizer用于指定自定义自定义分析器和规范器。

当我们在插入 document的时候,会发现有一个 _class字段会显示我们的类路径:

使用 Spring-Data-ElasticSearch操作ES_第1张图片

我们可以通过添加 @TypeAlias("xxxx")来修改这个值。

ElasticSearch操作:

spring data elasticsearch 使用多个接口来定义可以针对 elastic search索引调用的操作

  • IndexOperations 定义索引级别的操作,例如创建或删除索引。
  • DocumentOperations 定义基于 id 存储、更新和检索实体的操作。
  • SearchOperations 定义使用查询搜索多个实体的操作
  • ElasticsearchOperations结合了DocumentOperationsSearchOperations接口。

ElasticsearchRestTemplateElasticsearchOperations使用高级客户端的接口的实现。

我们无需对 这个模板接口进行特殊定义,因为在我们的继承配置类AbstractElasticsearchConfiguration就已经提供了 这个模板接口的 bean:

使用 Spring-Data-ElasticSearch操作ES_第2张图片

所以我们直接自动注入使用即可。

spring-data-elasticsearch 支持使用模板类进行CRUD的操作

插入document:
 @Test
void insert_By_Template(){
        Product product=new Product(333L,"title","cate",100.0,"/a.jsp",null);
        IndexQuery indexQuery=new  IndexQueryBuilder()
                .withObject(product)
                .build();
        template.index(indexQuery, IndexCoordinates.of("shopping"));
    }
查询document:
Product product = template.queryForObject(GetQuery.getById("333"), Product.class);

这是通过ID 查询检索实体

自定义查询:

ES的查询创建机制按照ES的请求方式创建

根据方法名创建查询:
interface BookRepository extends Repository<Book, String> {
  List<Book> findByNameAndPrice(String name, Integer price);
}

这样的方法名会被翻译成下面的json格式:

{
    "query": {
        "bool" : {
            "must" : [
                { "query_string" : { "query" : "?", "fields" : [ "name" ] } },
                { "query_string" : { "query" : "?", "fields" : [ "price" ] } }
            ]
        }
    }
}

我们并不需要自己定义方法的具体实现,只需要定义方法名,然后使用方法即可。

在这里插入图片描述

定义之后,直接使用:

在这里插入图片描述

即可查出具体内容:

在这里插入图片描述

注意我们在定义方法的时候就会有提示了:

使用 Spring-Data-ElasticSearch操作ES_第3张图片

关键词 参考名字 备注
And findByNameAndPrice
Or findByNameOrPrice
Is findByName 仅仅一个 match
Not findByNameNot { "query" : { "bool" : { "must_not" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }}
Between findByPriceBetween 包含上下界
LessThan findByPriceLessThan 少于,不包含上界
LessThanEqual findByPriceLessThanEqual 小于等于
Before findByPriceBefore 比当前值小,包含上下界(下界为null)
Like findByNameLike
OrderBy findByAvailableTrueOrderByNameDesc 降序排序所有的值
使用 @Query来创建查询

使用如下:

@Query("{\"match\": {\"name\": {\"query\": \"?0\"}}}")
List<Product> findMySelf();

这样,我们在使用 findMySelf()查询的时候,就会使用如下json查询:

{
  "query": {
    "match": {
      "name": {
        "query": "John"
      }
    }
  }
}

高亮显示:

我们要在console中能显示出高亮,那么必须要返回值设置为 SearchHit,如果返回的是实体类那么就不能查看出高亮

自定义方法:

@Highlight(fields ={ @HighlightField(name = "title")
    })
List<SearchHit<Product>> findByTitleAndPrice(String title, Double price);

我们直接使用该方法:

 List<SearchHit<Product>> hits = productDao.findByTitleAndPrice("hello", 267.0);
        System.out.println(hits);
        for (SearchHit<Product> hit : hits) {
            System.out.println(hit);
        }

在这里插入图片描述

可以发现,title字段确实被高亮显示了

聚合操作

对于聚合操作,spring data search 的 Repository并不支持,可能还是需要使用高级客户端去进行聚合的查询

  @Test
    void  use_aggregation() throws Exception{
        RestHighLevelClient client= new RestHighLevelClient(RestClient.builder(new HttpHost("localhost",9200,"http")));
        SearchRequest request=new SearchRequest();
        request.indices("shopping");
        AggregationBuilder aggregationBuilder= AggregationBuilders.max("maxprice").field("price");
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder().aggregation(aggregationBuilder);
        request.source(sourceBuilder);
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
        Max maxprice = search.getAggregations().get("maxprice");
        System.out.println(maxprice.getValue());
    }

分页查询:

需要使用分页的 Repository来操作:

@Repository
public interface ProductDaoPaging extends PagingAndSortingRepository<Product,Long> {
}
 @Autowired
    ProductDaoPaging dao;
    @Test
    void test(){
        PageRequest request=PageRequest.of(0,2);
        Page<Product> all = dao.findAll(request);
        Iterator<Product> iterator = all.iterator();
        while (iterator.hasNext()){
            Product next = iterator.next();
            System.out.println(next);
        }
    }

代码

依赖:

 <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.3.6.RELEASEversion>
        <relativePath/>
parent>
    <dependencies>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
        dependency>

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

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-devtoolsartifactId>
            <scope>runtimescope>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-testartifactId>
        dependency>
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-testartifactId>
        dependency>
    dependencies>

实体类:

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Document(indexName = "shopping",shards = 3,replicas = 1)
@TypeAlias("shopping")
public class Product {
    @Id
    private Long id;
    private String title;
    @Field(type = FieldType.Keyword)//keyword表示不能被分词
    private String category;
    @Field(type = FieldType.Double)//表示为浮点类型,非字符串类型都必须要使用这个
    private Double price;
    @Field(type = FieldType.Keyword,index = false) //不能被索引
    private String images;

    private List<Product> products;

}

Repository接口:

@Repository
public interface ProductDao extends ElasticsearchRepository<Product,Long>{
    
     List<Product> findByTitleAndCategory(String title, String category);

    @Highlight(fields ={
            @HighlightField(name = "title")
    })
    List<SearchHit<Product>> findByTitleAndPrice(String title, Double price);


    @Query("{\"match\": {\"name\": {\"query\": \"?0\"}}}")
     List<Product> findMySelf();
}

配置类:

@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {

        RestHighLevelClient client=new RestHighLevelClient(RestClient.builder(new HttpHost("localhost",9200)));
        return client;
    }
}

然后其他的就是一些测试代码,这里就不上了

你可能感兴趣的:(elasticsearch,spring,boot,elasticsearch,spring,boot,java)