目录
一、使用ElasticsearchRestTemplate类
3. ElasticsearchRepository接口的源码
5.1存储库方法可以定义为具有以下返回类型,用于返回多个元素:
操作ElasticSearch的数据,有两种方式一种是 ElasticsearchRepository 接口,另一种是ElasticsearchTemplate接口。SpringData对ES的封装ElasticsearchRestTemplate类,可直接使用,此类在ElasticsearchRestTemplate基础上进行性一定程度的封装,使用起来更方便灵活,拓展性更强。ElasticsearchRepository可以被继承操作ES,是SpringBoot对ES的高度封装,操作最为方便,但牺牲了灵活性。
Spring boot 和Elasticsearch版本关系:

- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
- </dependency>
- spring:
- elasticsearch:
- rest:
- uris: http://192.168.10.202:9200
- connection-timeout: 1s
- read-timeout: 1m
- username: elastic
- password: elastic
注意,如果es资源没有开启x-pack安全插件的话,可以不加username和password(因为默认是没有的)。
- import com.fasterxml.jackson.annotation.JsonFormat;
- import lombok.Data;
- import org.springframework.data.annotation.Id;
- import org.springframework.data.elasticsearch.annotations.DateFormat;
- import org.springframework.data.elasticsearch.annotations.Document;
- import org.springframework.data.elasticsearch.annotations.Field;
- import org.springframework.data.elasticsearch.annotations.FieldType;
- import java.time.LocalDate;
- import java.time.LocalDateTime;
- /**
- * @author Sinbad
- * @description: 测试ES对象
- * @date 2022/8/26 17:12
- */
- @Document(indexName = "mysql-test")
- @Data
- public class TestEsEntity {
- @Id
- Long id;
- @Field(type = FieldType.Text, name = "addr")
- String addr;
- @Field(type = FieldType.Text, name = "name")
- String name;
- @Field(type = FieldType.Date, name = "birthday", pattern = "yyyy-MM-dd")
- LocalDate birthday;
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8",locale = "zh_CN")
- @Field(type = FieldType.Date, name = "create_time", pattern = "yyyy-MM-dd HH:mm:ss",format =DateFormat.custom )
- LocalDateTime createTime;
- }
@Document注解:表示对应一个索引名相关的文档
@Data注解:lombok的,为类提供读写属性, 此外还提供了 equals()、hashCode()、toString() 方法
@Id 注解:表示文档的ID字段
@Field注解:文档字段的注解,对于日期含时间的字段,要写patten和format,不然会无法更新文档对象
@JsonFormat注解:将文档转换成JSON返回给前端时用到
注意日期类型字段不要用java.util.Date类型,要用java.time.LocalDate或java.time.LocalDateTime类型。
测试实例:
- import com.hkyctech.commons.base.entity.JsonResult;
- import com.hkyctech.tu.core.vo.TestEsEntity ;
- import lombok.extern.slf4j.Slf4j;
- import org.elasticsearch.index.query.BoolQueryBuilder;
- import org.elasticsearch.index.query.QueryBuilders;
- import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
- import org.springframework.data.domain.PageRequest;
- import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
- import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
- import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
- import org.springframework.data.elasticsearch.core.query.Query;
- import org.springframework.stereotype.Service;
- import javax.annotation.Resource;
-
-
- @Slf4j
- @Service
- public class ElasticSearchServiceImpl {
- @Resource
- ElasticsearchRestTemplate elasticsearchTemplate; //直接注入就可以用了
- /***
- * @description 查询全部数据
- */
- public Object testSearchAll(){
- Query query=elasticsearchTemplate.matchAllQuery();
- return elasticsearchTemplate.search(query, TestEsEntity .class);
- }
-
- /***
- * @description 精确查询地址字段
- * @param keyword 搜索关键字
- */
- public Object testSearchAddr(String keyword) {
- NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
- //查询条件
- .withQuery(QueryBuilders.queryStringQuery(keyword).defaultField("addr"))
- //分页
- .withPageable(PageRequest.of(0, 10))
- //高亮字段显示
- .withHighlightFields(new HighlightBuilder.Field(keyword))
- .build();
- return elasticsearchTemplate.search(nativeSearchQuery, TestEsEntity .class);
- }
-
- /***
- * @description 组合查询,查询关键词不分词,关系and
- */
- public Object testComboSearchAnd(){
- BoolQueryBuilder esQuery=QueryBuilders.boolQuery()
- .must(QueryBuilders.termQuery("addr", "深圳"))
- .must(QueryBuilders.termQuery("addr", "广东"));
-
- NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
- //查询条件
- .withQuery(esQuery)
- //分页
- .withPageable(PageRequest.of(0, 10))
- .build();
- return elasticsearchTemplate.search(nativeSearchQuery, TestEsEntity .class);
- }
-
-
- /***
- * @description 组合查询,查询关键词不分词,关系or
- */
- public Object testComboSearchOr(){
- BoolQueryBuilder esQuery=QueryBuilders.boolQuery()
- .should(QueryBuilders.termQuery("addr", "深圳"))
- .should(QueryBuilders.termQuery("addr", "广东"));
-
- NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
- //查询条件
- .withQuery(esQuery)
- //分页
- .withPageable(PageRequest.of(0, 10))
- .build();
- return elasticsearchTemplate.search(nativeSearchQuery, TestEsEntity .class);
- }
-
- /***
- * @description 索引或更新文档
- * @param vo 文档对象
- */
- public JsonResult testPutDocument(TestEsEntity vo){
- try {
- Object data = elasticsearchTemplate.save(vo);
- return JsonResult.getSuccessResult(data,"更新成功");
- }catch (Exception e){
- // 看http请求响应日志其实操作成功了,但是会报解析出错,可能是spring的bug,这里拦截一下
- String message=e.getMessage();
- if(message.indexOf("response=HTTP/1.1 200 OK")>0 || message.indexOf("response=HTTP/1.1 201 Created")>0){
- return JsonResult.getSuccessResult("更新成功");
- }
- return JsonResult.getFailResult(e.getStackTrace(),e.getMessage());
- }
- }
-
- /***
- * @description 删除文档
- * @param id 文档ID
- */
- public JsonResult deleteDocument(String id){
- try {
- elasticsearchTemplate.delete(id, TestEsEntity .class);
- return JsonResult.getSuccessResult("删除成功");
- }catch (Exception e){
- String message=e.getMessage();
- // 看http请求响应日志其实操作成功了,但是会报解析出错,可能是spring的bug,这里拦截一下
- if(message.indexOf("response=HTTP/1.1 200 OK")>0 ){
- return JsonResult.getSuccessResult("删除成功");
- }
- return JsonResult.getFailResult(e.getStackTrace(),e.getMessage());
- }
- }
- }
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
- </dependency>
- spring:
- elasticsearch:
- rest:
- uris: http://192.168.10.202:9200
- connection-timeout: 1s
- read-timeout: 1m
- username: elastic
- password: elastic
- package org.springframework.data.elasticsearch.repository;
-
- import java.io.Serializable;
-
- import org.elasticsearch.index.query.QueryBuilder;
- import org.springframework.data.domain.Page;
- import org.springframework.data.domain.Pageable;
- import org.springframework.data.elasticsearch.core.query.SearchQuery;
- import org.springframework.data.repository.NoRepositoryBean;
-
- @NoRepositoryBean
- public interface ElasticsearchRepository<T, ID extends Serializable> extends ElasticsearchCrudRepository<T, ID> {
-
- <S extends T> S index(S entity);
-
- Iterable<T> search(QueryBuilder query);
-
- Page<T> search(QueryBuilder query, Pageable pageable);
-
- Page<T> search(SearchQuery searchQuery);
-
- Page<T> searchSimilar(T entity, String[] fields, Pageable pageable);
-
- void refresh();
-
- Class<T> getEntityClass();
- }
- package org.springframework.data.repository;
-
- import java.util.Optional;
-
- /**
- * Interface for generic CRUD operations on a repository for a specific type.
- *
- * @author Oliver Gierke
- * @author Eberhard Wolff
- */
- @NoRepositoryBean
- public interface CrudRepository<T, ID> extends Repository<T, ID> {
-
- /**
- * Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
- * entity instance completely.
- *
- * @param entity must not be {@literal null}.
- * @return the saved entity will never be {@literal null}.
- */
- <S extends T> S save(S entity);
-
- /**
- * Saves all given entities.
- *
- * @param entities must not be {@literal null}.
- * @return the saved entities will never be {@literal null}.
- * @throws IllegalArgumentException in case the given entity is {@literal null}.
- */
- <S extends T> Iterable<S> saveAll(Iterable<S> entities);
-
- /**
- * Retrieves an entity by its id.
- *
- * @param id must not be {@literal null}.
- * @return the entity with the given id or {@literal Optional#empty()} if none found
- * @throws IllegalArgumentException if {@code id} is {@literal null}.
- */
- Optional<T> findById(ID id);
-
- /**
- * Returns whether an entity with the given id exists.
- *
- * @param id must not be {@literal null}.
- * @return {@literal true} if an entity with the given id exists, {@literal false} otherwise.
- * @throws IllegalArgumentException if {@code id} is {@literal null}.
- */
- boolean existsById(ID id);
-
- /**
- * Returns all instances of the type.
- *
- * @return all entities
- */
- Iterable<T> findAll();
-
- /**
- * Returns all instances of the type with the given IDs.
- *
- * @param ids
- * @return
- */
- Iterable<T> findAllById(Iterable<ID> ids);
-
- /**
- * Returns the number of entities available.
- *
- * @return the number of entities
- */
- long count();
-
- /**
- * Deletes the entity with the given id.
- *
- * @param id must not be {@literal null}.
- * @throws IllegalArgumentException in case the given {@code id} is {@literal null}
- */
- void deleteById(ID id);
-
- /**
- * Deletes a given entity.
- *
- * @param entity
- * @throws IllegalArgumentException in case the given entity is {@literal null}.
- */
- void delete(T entity);
-
- /**
- * Deletes the given entities.
- *
- * @param entities
- * @throws IllegalArgumentException in case the given {@link Iterable} is {@literal null}.
- */
- void deleteAll(Iterable<? extends T> entities);
-
- /**
- * Deletes all entities managed by the repository.
- */
- void deleteAll();
- }
List
Stream
SearchHits
List
Stream
SearchPage
使用@query注释对方法声明query。
- interface BookRepository extends ElasticsearchRepository<Book, String> {
- @Query("{\"match\": {\"name\": {\"query\": \"?0\"}}}")
- Page<Book> findByName(String name,Pageable pageable);
- }
-
设置为注释参数的字符串必须是有效的 Elasticsearch JSON 查询。 它将作为查询元素的值发送到Easticsearch;例如,如果使用参数 John 调用函数,它将生成以下查询正文:
- {
- "query": {
- "match": {
- "name": {
- "query": "John"
- }
- }
- }
- }
对@Query采用集合参数的方法进行注释
- @Query("{\"ids\": {\"values\": ?0 }}")
- List<SampleEntity> getByIds(Collection<String> ids);
-
将进行ID查询以返回所有匹配的文档。因此,调用List为[“id1”、“id2”、“id3”]的方法将生成查询主体
- {
- "query": {
- "ids": {
- "values": ["id1", "id2", "id3"]
- }
- }
- }
- public interface LogRepository extends ElasticsearchRepository<Log, String> {
- /**
- * 定义一个方法查询:根据title查询es
- *
- * 原因: ElasticsearchRepository会分析方法名,参数对应es中的field(这就是灵活之处)
- * @param title
-
- */
- List<Log> findBySummary(String summary);
- List<Log> findByTitle(String title);
-
- /**
- * 定义一个方法查询: 根据title,content查询es
- */
- List<Log> findByTitleAndContent(String title, String content);
-
- }
- @PostMapping("save")
- public void save(@Validated @RequestBody Log req){
- Log dto = new Log();
- dto.setTitle(req.getTitle());
- dto.setSummary(req.getSummary());
- dto.setContent(req.getContent());
- dto.setCreateTime(new Date());
- dto.setId(req.getId());
- LogRepository.save(dto);
- return ;
- }
-
- @PostMapping("testTitle")
- public void testSearchTitle(@Validated @RequestBody Log req){
- List<Log> searchResult = logRepository.findByTitle(req.getMobileType());
- Iterator<Log> iterator = searchResult.iterator();
- while(iterator.hasNext()){
- System.out.println(iterator.next());
- }
- System.out.println("sa");
- return;
- }