使用 Spring-Data-ElasticSearch操作ES


今天在学 尚硅谷的 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字段会显示我们的类路径:

在这里插入图片描述

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

ElasticSearch操作:

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

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

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

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

在这里插入图片描述

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

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" ] } }
            ]
        }
    }
}

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

在这里插入图片描述

定义之后,直接使用:

在这里插入图片描述

即可查出具体内容:

在这里插入图片描述

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

在这里插入图片描述

关键词参考名字备注
AndfindByNameAndPrice
OrfindByNameOrPrice
IsfindByName仅仅一个 match
NotfindByNameNot{ "query" : { "bool" : { "must_not" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }}
BetweenfindByPriceBetween包含上下界
LessThanfindByPriceLessThan少于,不包含上界
LessThanEqualfindByPriceLessThanEqual小于等于
BeforefindByPriceBefore比当前值小,包含上下界(下界为null)
LikefindByNameLike
OrderByfindByAvailableTrueOrderByNameDesc降序排序所有的值
使用 @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.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.6.RELEASE</version>
        <relativePath/>
</parent>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
        </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;
    }
}

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

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值