首先要确保自己引入的spring-boot-starter-data-elasticsearch版本与elasticsearch一直,通常情况下会遇到使用了如,spring-boot-dependencies,parent等版本依赖管理导致es版本不对应的情况。此时记得手动指定如下jar版本例如我使用的是7.12.0:
org.springframework.data
spring-data-elasticsearch
4.2.0
org.elasticsearch.client
elasticsearch-rest-high-level-client
${elasticsearch.version}
org.elasticsearch
elasticsearch
${elasticsearch.version}
org.elasticsearch.client
elasticsearch-rest-client
${elasticsearch.version}
版本对应关系:https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#preface.versions
这里简单使用配置文件方式演示
elasticsearch:
rest:
username: elastic
password: xxxxxx
uris: http://xxxxxxxxxx:9200
connection-timeout: 1000
read-timeout: 1000
二、创建索引映射
这里我们尽量使用spring-data提供的自动创建方式,避免手动创建致使字段无法对应导致出错。尤其是date类型字段最容易产生问题,依照下方实例spring在启动时会自动判断是否已经创建如果没有会自动帮我们创建。
@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface document {
String indexName(); // 索引库的名称,个人建议以项目的名称命名
@Deprecated
String type() default ""; // 类型,7.x之后以废弃
short shards() default 1;//默认分区数
short replicas() default 1; // 每个分区默认的备份数
String refreshInterval() default "1s"; // 刷新间隔
String indexStoreType() default "fs"; // 索引文件存储类型
boolean createIndex() default true; // 是否创建索引
VersionType versionType() default VersionType.EXTERNAL; // 版本
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@document(indexName = "longzhu")
@Builder
public class Product {
@Id
long id;
@Field(type = FieldType.Keyword)
private String territory;
@Field(type = FieldType.Keyword)
private String ip;
@Field(type = FieldType.Keyword)
private String type;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String name;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String description;
@Field(type = FieldType.Text)
private String production;
@Field(type = FieldType.Date,format = DateFormat.year_month_day)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "uuuu-MM-dd", timezone = "GMT+8")
private LocalDate productionTime;
@Field(type = FieldType.Double)
private Double price;
@Field(type = FieldType.Double, index = false)
private Double currentPrice;
@Field(type = FieldType.Double)
private Double height;
@Field(type = FieldType.Double, index = false)
private Double weight;
}
启动后我们在kibana查询一下确保创建成功,GET /longzhu
基础操作使用很简单,我们只需要创建一个接口继承ElasticsearchRepository就可以帮我自动代理生成一些基础操作方法,同时也支持如spring-data-jpa一样通过方法名称自动帮我们生成对应查询操作,如我下方自定义了一个根据名称查询的接口。
@Repository public interface ProductDao extends ElasticsearchRepository{ List findByName(String name); }
详情可参考官方提问的文档https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.repositories
四、@Query注解查询这种方式用到的场景相对较少,我们简单看一下官方给出的实例
interface BookRepository extends ElasticsearchRepository{ @Query("{"match": {"name": {"query": "?0"}}}") Page findByName(String name,Pageable pageable); }
The String that is set as the annotation argument must be a valid Elasticsearch JSON query. It will be sent to Easticsearch as value of the query element; if for example the function is called with the parameter John, it would produce the following query body:
{
"query": {
"match": {
"name": {
"query": "John"
}
}
}
}
五、restTemplate高级查询
1.常规
在进行restTemplate.search(Query var1, Class var2);调用时我们发现都需要传入一个query参数。从下图看到其下有三个实现类,我们最常用到的就是NatviveSearchQuery原生查询的方法。
下面是一个简单的分页+排序的案例:
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
NativeSearchQuery query = queryBuilder
.withQuery(QueryBuilders.multiMatchQuery("景品","type"))
// 分页
.withPageable(PageRequest.of(0,10))
// 根据查询结果按时间升序
.withSort(SortBuilders.fieldSort("productionTime").order(SortOrder.ASC)).build();
SearchHits searchHits = restTemplate.search(query,Product.class);
searchHits.stream().iterator().forEachRemaining(System.out::println);
上面的写法也可以简写为:
withPageable(PageRequest.of(0,10, Sort.Direction.ASC, "productionTime"))
我们看到of()方法结尾是一个可变参数,所以允许我们传入多个排序字段。如果在日期相同的情况下我们想根据手办高度排序即只需要再追加一个高度字段
withPageable(PageRequest.of(0,10, Sort.Direction.ASC, "productionTime","height"))
更多有趣的API还需要我们自己去慢慢探索
2.高亮// 默认样式
.withHighlightFields(new HighlightBuilder.Field("type"))
// 自定义
.withHighlightBuilder(new HighlightBuilder().field("type").preTags(" ").postTags("
"))



