Elasticsearch与SpringBoot进行集成(未完)
Elasticsearch具体版本强依赖性
Elasticsearch以及其周边的相关平台都是强版本依赖的,升级过程也需要升级其他相关组件。
目前Elasticsearch的6.x相当于3.x。之所以从2一跃跳到6,Elastic体系内还有Kibana,Logstash,Beats等产品。为了统一各产品版本,所以直接将Elasticsearch的版本从2提升到6 ,6.x版本提供了许多新的特性,并且基于Lucene7.x
性能方面:
1.磁盘空间可以节省近一半
2.索引时间减少近50%
3.查询性能提升近30%
4.支持IPV6
性能的具体数据可以查看Elasticsearch性能监控。性能的提升主要是Lucene6版本之后的很多底层结构的优化。Lucene6使用Block K-D trees
数据结构来构建索引。BKD Trees
是一种可以动态扩展的KD-tree
结构。
想了解BKD Trees可以参考:
https://users.cs.duke.edu/~pankaj/publications/papers/bkd-sstd.pdf
Elasticsearch也是一种数据库,属于非关系型数据库,不需要自己建库建表
与SpringBoot进行集成
实体类:
@Data
@Document(indexName = "province", type = "city")
public class City implements Serializable {
@Id
@Field(fielddata = true)
private Long id;
private String score;
private String name;
private String description;
}
加上@Id
注解后,在Elasticsearch里对应的该列就是主键了,在查询时就可以直接用主键查询
相关代码说明:
@Document源码
@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Document {
String indexName();
String type() default "";
boolean useServerConfiguration() default false;
short shards() default 5;
short replicas() default 1;
String refreshInterval() default "1s";
String indexStoreType() default "fs";
boolean createIndex() default true;
}
indexName()
:索引库的名称,建议以项目的名称命名,类似于关系型数据库中数据库
type()
:类型,建议以实体的名称命名,类似于关系型数据库中数据库表
useServerConfiguration()
:是否使用服务器配置
shards()
:默认分区数
replicas()
:每个分区默认的备份数
refreshInterval()
:刷新间隔
indexStoreType()
:索引文件存储类型
createIndex()
:是否创建索引
@Field源码
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
@Inherited
public @interface Field {
FieldType type() default FieldType.Auto;
boolean index() default true;
DateFormat format() default DateFormat.none;
String pattern() default "";
boolean store() default false;
boolean fielddata() default false;
String searchAnalyzer() default "";
String analyzer() default "";
String normalizer() default "";
String[] ignoreFields() default {};
boolean includeInParent() default false;
String[] copyTo() default {};
}
type()
:类型,默认自动检测,也可以根据实际情况设置
index()
:原来的analyzed/not_analyzed/no
变为只接受boolean
值。分别代替not_analyzed/no
format()
:时间类型的格式化
store()
:是否存储原文
searchAnalyzer()
:指定字段搜索时使用的分词器
ignoreFields()
:忽略某个字段
注:因为Elasticsearch
6.x中的Mapping
改变,原有的@Field(type = FieldType.string)
类型的索引映射需要替换成@Field(type = FieldType.Keyword)
或者@Field(type = FieldType.Text)
。 要精确搜索就用Keyword
,否则用Text
。如果不需要通过该字段进行查询,则index
设置false
即可。
可能出现的报错:
Caused by: java.lang.IllegalArgumentException: mapper [xx] of different type, current_type [xxx], merged_type [xxx]
因为索引已经存在了,创建索引时不会覆盖原有的,所以删除原有的就不会报错了
数据操作层
Spring Data JPA和Spring Data Elasticsearch共享相同的通用基础架构。与JPA存储库一样,基本原则是基于方法名称自动构造查询。
public interface CityRepository extends ElasticsearchRepository<City,Long> {
}
ElasticsearchRepository源码
@NoRepositoryBean
public interface ElasticsearchRepository<T, ID extends Serializable> extends ElasticsearchCrudRepository<T, ID> {
<S extends T> S index(S var1);
Iterable<T> search(QueryBuilder var1);
Page<T> search(QueryBuilder var1, Pageable var2);
Page<T> search(SearchQuery var1);
Page<T> searchSimilar(T var1, String[] var2, Pageable var3);
void refresh();
Class<T> getEntityClass();
}
为什么具有Crud操作呢
注意看以下继承关系
public interface ElasticsearchCrudRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID>
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID>
不难发现最后有继承CrudRepository
接口
CrudRepository源码
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S var1);
<S extends T> Iterable<S> saveAll(Iterable<S> var1);
Optional<T> findById(ID var1);
boolean existsById(ID var1);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> var1);
long count();
void deleteById(ID var1);
void delete(T var1);
void deleteAll(Iterable<? extends T> var1);
void deleteAll();
}
控制层
实现简单的添加功能
@RestController
public class CityRestController {
private final CityRepository cityRepository;
@Autowired
public CityRestController(CityRepository cityRepository) {
this.cityRepository = cityRepository;
}
@PostMapping("/api/city")
public City createCity(@RequestBody City city) {
return cityRepository.save(city);
}
}
yml配置文件
spring:
data:
elasticsearch:
cluster-nodes: localhost:9300
cluster-name: my-application
server:
port: 8888
注:记得修改目录config
下的elasticsearch.yml
配置文件
1.把cluster.name:my-application
注释打开
2.network.host
改为localhost
,也就是network.host: localhost
下面使用postman测试下
image.png再插入一条数据
{
"id":2,
"score":"5",
"name":"广州",
"description":"也是一线城市"
}
查看Elasticsearch的数据
head插件下
image.pngkibana客户端下
第一次进入kibana如果提示没索引就创建下,索引名就是indexName
有Table和JSON两种查看方式
注:插入数据的主键如果相同,新数据将会覆盖旧数据
推荐参考:
接口文档:
https://docs.spring.io/spring-data/elasticsearch/docs/3.1.3.RELEASE/reference/html/
API文档:
https://docs.spring.io/spring-data/elasticsearch/docs/3.1.3.RELEASE/api/