Elasticsearch SpringBoot

Elasticsearch与SpringBoot进行集成(未完)

2018-12-29  本文已影响8人  意识流丶

Elasticsearch具体版本强依赖性

Elasticsearch以及其周边的相关平台都是强版本依赖的,升级过程也需要升级其他相关组件。
目前Elasticsearch的6.x相当于3.x。之所以从2一跃跳到6,Elastic体系内还有KibanaLogstashBeats等产品。为了统一各产品版本,所以直接将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():忽略某个字段

注:因为Elasticsearch6.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.png

kibana客户端下

第一次进入kibana如果提示没索引就创建下,索引名就是indexName
有Table和JSON两种查看方式

image.png
注:插入数据的主键如果相同,新数据将会覆盖旧数据

推荐参考:

接口文档:
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/

上一篇下一篇

猜你喜欢

热点阅读