admin

Spring Data Elasticsearch 的简单使用
前言本实例只是用作快速入门使用,这段时间自己将 3 年前的DHT网络爬虫重新写了一遍,一来是因为之前的程序代码写的...
扫描右侧二维码阅读全文
26
2019/02

Spring Data Elasticsearch 的简单使用

前言

本实例只是用作快速入门使用,这段时间自己将 3 年前的DHT网络爬虫重新写了一遍,一来是因为之前的程序代码写的非常杂乱,性能也不是很好,数据到了1600万的时候就爬不动数据了;二来是借此实战一波 Spring Cloud 微服务的开发。
3年前用的Mysql存储数据,由于存储的数据字段长度比较大,所以此次决定直接拿Elasticsearch来当做数据库使用,集全文检索于一体,何乐而不为。
实战之前也是先搜索了一波Elasticsearch能不能当做数据库来使用,发现还是有人是这样来用的,所以暂且不管后面是否存在性能问题,是否有坑,也先实验一波再说。

集成

Spring boot项目需要添加如下依赖:

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

Elasticsearch的安装在前一篇文章已经说过了,所以这里不再赘述。

application.yml中添加如下配置:

spring:
  data:
    elasticsearch:
      cluster-nodes: 127.0.0.1:9300
      repositories:
        enabled: true
      properties:
        path:
          logs: ./elasticsearch/log #elasticsearch日志存储目录
          data: ./elasticsearch/data #elasticsearch数据存储目录

接下来的使用就是Spring data系列的相同套路了,Spring data对各种数据库操作进行的封装都大同小异,依葫芦画瓢照着来创建Repository即可,既然是使用Spring Data Elasticsearch,那么我们新建的Repository接口就是继承ElasticsearchRepository接口了。
查看ElasticsearchRepository有哪些接口可供使用:

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();
}

可以看到它包含了几个搜索的接口和一个索引的接口,除此之外,它还继承了ElasticsearchCrudRepository,从名字上就可以知道它包含了一系列的增删改查接口,实际上它上面还继承了一系列的接口,这里我直接找到上面关键的一个接口类:

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();
}

我们使用的时候只需要新建接口继承ElasticsearchRepository即可,无需添加注解,下面是我新建的一个Repository接口:

public interface TorrentRepository extends ElasticsearchRepository<Torrent, String>, TorrentDao {
}

上面的接口中我没有定义任何方法是因为我暂时还用不到其他方法,实际上它也支持findByXXX这种形式的接口定义,具体可参见官方文档
除此之外,可以看到我上面还继承了TorrentDao,这是我以前使用Spring Data JPA时学习的自定义扩展Repository,也可以说是Spring Data操作数据库的高级用法,Spring Data JPA中就是操作entityManager来做更加复杂的查询。
Spring Data Elasticsearch也是一样用法,可以直接使用elasticsearchTemplate来做高级操作。

比如我这里,继承的ElasticsearchRepository,里面包含的一些接口不能满足我的现有需求:

数据库不存在则插入,存在则更新的操作(不知道 ElasticsearchRepository 中的 save() 方法是否能够做到)

所以选择使用elasticsearchTemplate来做高级操作。
用法如下,新建TorrentDao接口:

/***
 * 自定义扩展 Torrent Dao
 *
 * @author Mr.Xu
 * @since 2019-02-25 11:07
 **/
public interface TorrentDao {
    /**
    * 存在则更新,不存在则插入
    *
    * @param torrent
    * @return void
    */
    void upsert(Torrent torrent) throws IOException;
}

接着添加其实现类TorrentDaoImpl.java

/***
 * 自定义扩展 Torrent Dao 实现类
 *
 * @author Mr.Xu
 * @since 2019-02-25 11:09
 **/
public class TorrentDaoImpl implements TorrentDao {

    @Autowired
    private ElasticsearchTemplate template;

    @Override
    public void upsert(Torrent torrent) throws IOException {
        Client client = template.getClient();

        XContentBuilder source = jsonBuilder()
                .startObject()
                .field("fileType", torrent.getFileType())
                                .field("filesize", torrent.getFilesize())
                .field("createDate", torrent.getCreateDate())
                .field("files", torrent.getFiles())
                .endObject();

        IndexRequest indexRequest = new IndexRequest("dodder", "torrent", torrent.getInfoHash())
                .source(source);
        UpdateRequest updateRequest = new UpdateRequest("dodder", "torrent", torrent.getInfoHash())
                .doc(source)
                .upsert(indexRequest);
        client.update(updateRequest);
    }
}

最后直接在继承ElasticsearchRepository接口的类也继承我们自定义的接口即可,如下:

public interface TorrentRepository extends ElasticsearchRepository<Torrent, String>, TorrentDao {
}
Last modification:February 26th, 2019 at 03:53 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment