Spring Boot + Elasticsearch 实现索引的日常维护

全文检索的应用越来越广泛,几乎成了互联网应用的标配,商品搜索、日志分析、历史数据归档等等,各种场景都会涉及到大批量的数据,在全文检索方面,方案无外乎Lucene、Solr、Elasticsearch三种应用的较为广泛。es、solr的底层都依托于Lucene,但es比solr学习成本更低,由于其提供的RESTful API简单快捷,对互联网应用开发而言更是如虎添翼。

下面结合以实际案例,通过Java API的形式操作es数据集。

框架选型基础是Spring Boot + Spring-data-elasticsearch + elasticsearch。

使用ElasticsearchRepository的形式来连接、维护ES数据集,ElasticsearchRepository中提供了简单的操作索引数据的方法集合,继承自ElasticsearchCrudRepository,涵盖了CRUD、排序、分页等常见的基本操作功能。

  1. @NoRepositoryBean  

  2. public interface ElasticsearchRepository<T, ID extends Serializable> extends ElasticsearchCrudRepository<T, ID> {  

  3.    <S extends T> S index(S var1);  

  4.    Iterable<T> search(QueryBuilder var1);  

  5.    Page<T> search(QueryBuilder var1, Pageable var2);  

  6.    Page<T> search(SearchQuery var1);  

  7.    Page<T> searchSimilar(T var1, String[] var2, Pageable var3);  

  8.    void refresh();  

  9.    Class<T> getEntityClass();  

  10. }  

从基本的pom配置开始

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  2.    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  3.    <modelVersion>4.0.0</modelVersion>

  4.    <groupId>com.esp.index.data</groupId>

  5.    <artifactId>esp-cube</artifactId>

  6.    <version>0.0.1-SNAPSHOT</version>

  7.    <parent>

  8.        <groupId>org.springframework.boot</groupId>

  9.        <artifactId>spring-boot-starter-parent</artifactId>

  10.        <version>1.5.2.RELEASE</version>

  11.        <relativePath /> <!-- lookup parent from repository -->

  12.    </parent>

  13.    <properties>

  14.        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

  15.        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

  16.        <java.version>1.7</java.version>

  17.    </properties>

  18.    <dependencies>

  19.        <dependency>

  20.            <groupId>org.springframework.boot</groupId>

  21.            <artifactId>spring-boot-starter-jdbc</artifactId>

  22.            <exclusions>

  23.                <exclusion>

  24.                    <groupId>org.apache.tomcat</groupId>

  25.                    <artifactId>tomcat-jdbc</artifactId>

  26.                </exclusion>

  27.            </exclusions>

  28.        </dependency>

  29.        <dependency>

  30.            <groupId>org.springframework.boot</groupId>

  31.            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>

  32.        </dependency>

  33.        <dependency>

  34.            <groupId>org.springframework.boot</groupId>

  35.            <artifactId>spring-boot-starter-web</artifactId>

  36.            <exclusions>

  37.                <exclusion>

  38.                    <artifactId>log4j-over-slf4j</artifactId>

  39.                    <groupId>org.slf4j</groupId>

  40.                </exclusion>

  41.            </exclusions>

  42.        </dependency>

  43.        <dependency>

  44.            <groupId>org.springframework.boot</groupId>

  45.            <artifactId>spring-boot-starter</artifactId>

  46.            <exclusions>

  47.                <exclusion>

  48.                    <groupId>org.springframework.boot</groupId>

  49.                    <artifactId>spring-boot-starter-logging</artifactId>

  50.                </exclusion>

  51.            </exclusions>

  52.        </dependency>

  53.        <dependency>

  54.            <groupId>org.springframework.boot</groupId>

  55.            <artifactId>spring-boot-starter-test</artifactId>

  56.            <scope>test</scope>

  57.        </dependency>

  58.        <dependency>

  59.            <groupId>org.springframework.boot</groupId>

  60.            <artifactId>spring-boot-starter-log4j</artifactId>

  61.            <version>1.3.1.RELEASE</version>

  62.        </dependency>

  63.    </dependencies>

  64.    <build>

  65.        <finalName>esp-cube</finalName>

  66.        <plugins>

  67.            <plugin>

  68.                <groupId>org.springframework.boot</groupId>

  69.                <artifactId>spring-boot-maven-plugin</artifactId>

  70.            </plugin>

  71.        </plugins>

  72.    </build>

  73. </project>

编写自己的Resository操作类

  1. public interface ArticleSearchRepository extends ElasticsearchRepository<Article, Long>{

  2.    List<Article> findByAbstractsAndContent(String abstracts, String content);

  3. }

其中Article为是与elasticsearch连接的实体类,类似于PO的概念,其中指定的索引名称、类型名称、及分片、副本数量等要素。

  1. @Data

  2. @Document(indexName = "article_index", type = "article", shards = 5, replicas = 1, indexStoreType = "fs", refreshInterval = "-1")

  3. public class Article implements Serializable {

  4.    /**

  5.     * serialVersionUID:

  6.     *

  7.     * @since JDK 1.6

  8.     */

  9.    private static final long serialVersionUID = 1L;

  10.    @Id

  11.    private Long id;

  12.    /** 标题 */

  13.    private String title;

  14.    /** 摘要 */

  15.    private String abstracts;

  16.    /** 内容 */

  17.    private String content;

  18.    /** 发表时间 */

  19.    @Field(format = DateFormat.date_time, index = FieldIndex.no, store = true, type = FieldType.Object)

  20.    private Date postTime;

  21.    /** 点击率 */

  22.    private Long clickCount;

  23. }

我们需要定义域的实体和一个Spring data的基本的CRUD支持库类。用id注释定义标识符字段,如果你没有指定ID字段,Elasticsearch不能索引你的文件。同时需要指定索引名称类型,@Document注解也有助于我们设置分片和副本数量。

接口类

  1. public interface ArticleService {

  2.    /**

  3.     * saveArticle: 写入<br/>

  4.     *

  5.     * @author guooo Date:2017年9月27日下午3:20:06

  6.     * @param article

  7.     * @return

  8.     * @since JDK 1.6

  9.     */

  10.    long saveArticle(Article article);

  11.    /**

  12.     * deleteArticle: 删除,并未真正删除,只是查询不到<br/>

  13.     *

  14.     * @author guooo Date:2017年9月27日下午3:20:08

  15.     * @param id

  16.     * @since JDK 1.6

  17.     */

  18.    void deleteArticle(long id);

  19.    /**

  20.     * findArticle: <br/>

  21.     *

  22.     * @author guooo Date:2017年9月27日下午3:20:10

  23.     * @param id

  24.     * @return

  25.     * @since JDK 1.6

  26.     */

  27.    Article findArticle(long id);

  28.    /**

  29.     * findArticlePageable: <br/>

  30.     *

  31.     * @author guooo Date:2017年9月27日下午3:20:13

  32.     * @return

  33.     * @since JDK 1.6

  34.     */

  35.    List<Article> findArticlePageable();

  36.    /**

  37.     * findArticleAll: <br/>

  38.     *

  39.     * @author guooo Date:2017年9月27日下午3:20:15

  40.     * @return

  41.     * @since JDK 1.6

  42.     */

  43.    List<Article> findArticleAll();

  44.    /**

  45.     * findArticleSort: <br/>

  46.     *

  47.     * @author guooo Date:2017年9月27日下午3:20:18

  48.     * @return

  49.     * @since JDK 1.6

  50.     */

  51.    List<Article> findArticleSort();

  52.    /**

  53.     * search: <br/>

  54.     *

  55.     * @author guooo Date:2017年9月27日下午3:20:22

  56.     * @param content

  57.     * @return

  58.     * @since JDK 1.6

  59.     */

  60.    List<Article> search(String content);

  61.    /**

  62.     * update: es没有修改操作,结合save操作完成<br/>

  63.     *

  64.     * @author guooo Date:2017年9月27日下午3:20:25

  65.     * @param id

  66.     * @return

  67.     * @since JDK 1.6

  68.     */

  69.    long update(long id);

  70. }

接口实现

  1. @Service

  2. public class ArticleServiceImpl implements ArticleService {

  3.    final int page = 0;

  4.    final int size = 10;

  5.    /* 搜索模式 */

  6.    String SCORE_MODE_SUM = "sum"; // 权重分求和模式

  7.    Float MIN_SCORE = 10.0F; // 由于无相关性的分值默认为 1 ,设置权重分最小值为 10

  8.    Pageable pageable = new PageRequest(page, size);

  9.    @Autowired

  10.    ArticleSearchRepository repository;

  11.    @Override

  12.    public long saveArticle(Article article) {

  13.        Article result = repository.save(article);

  14.        return result.getId();

  15.    }

  16.    @Override

  17.    public void deleteArticle(long id) {

  18.        repository.delete(id);

  19.    }

  20.    @Override

  21.    public Article findArticle(long id) {

  22.        return repository.findOne(id);

  23.    }

  24.    @Override

  25.    public List<Article> findArticlePageable() {

  26.        return repository.findAll(pageable).getContent();

  27.    }

  28.    @Override

  29.    public List<Article> findArticleAll() {

  30.        Iterable<Article> iterables = repository.findAll();

  31.        List<Article> articles = new ArrayList<>();

  32.        for (Article article : iterables) {

  33.            articles.add(article);

  34.        }

  35.        return articles;

  36.    }

  37.    @Override

  38.    public List<Article> findArticleSort() {

  39.        List<Order> orders = new ArrayList<>();

  40.        Order order = new Order(Direction.ASC, "clickCount");

  41.        orders.add(order);

  42.        Sort sort = new Sort(orders);

  43.        Iterable<Article> iterables = repository.findAll(sort);

  44.        List<Article> articles = new ArrayList<>();

  45.        for (Article article : iterables) {

  46.            articles.add(article);

  47.        }

  48.        return articles;

  49.    }

  50.    @Override

  51.    public List<Article> search(String content) {

  52.        return repository.findByAbstractsAndContent(content, content);

  53.    }

  54.    @Override

  55.    public long update(long id) {

  56.        Article article = repository.findOne(id);

  57.        article.setTitle("test");

  58.        Article retun = repository.save(article);

  59.        System.out.println(retun.getId()+"更新的数据");

  60.        return retun.getId();

  61.    }

  62. }

是不是与JPA、hibernate操作数据集的手法很类似?

controller方法类:

  1. @RestController

  2. @RequestMapping(value = "/article")

  3. public class APIArticleController {

  4.    @Autowired

  5.    ArticleService articleService;

  6.    @RequestMapping(value = "save", method = RequestMethod.POST)

  7.    public long save() {

  8.        for (int i = 10000; i < 12000; i++) {

  9.            Article article = new Article();

  10.            article.setClickCount(Long.valueOf(i + RandomUtils.nextInt(23, i)));

  11.            article.setAbstracts("我的一个测试" + i);

  12.            article.setContent(i + "这是第一个测试的内容@spring-data-elasticsearch");

  13.            article.setPostTime(new Date());

  14.            article.setId(Long.valueOf(RandomUtils.nextLong(i, i)));

  15.            long _id = articleService.saveArticle(article);

  16.            System.out.println(_id);

  17.        }

  18.        return 23;

  19.    }

  20.    @RequestMapping(value = "delete", method = RequestMethod.POST)

  21.    public void deleteArticle(long id) {

  22.        articleService.deleteArticle(id);

  23.    }

  24.    @RequestMapping(value = "findOne", method = RequestMethod.POST)

  25.    public Article findArticle(long id) {

  26.        return articleService.findArticle(id);

  27.    }

  28.    @RequestMapping(value = "findArticlePageable", method = RequestMethod.POST)

  29.    public List<Article> findArticlePageable() {

  30.        return articleService.findArticlePageable();

  31.    }

  32.    @RequestMapping(value = "findArticleAll", method = RequestMethod.POST)

  33.    public List<Article> findArticleAll() {

  34.        return articleService.findArticleAll();

  35.    }

  36.    @RequestMapping(value = "findArticleSort", method = RequestMethod.POST)

  37.    public List<Article> findArticleSort() {

  38.        return articleService.findArticleSort();

  39.    }

  40.    @RequestMapping(value = "search", method = RequestMethod.POST)

  41.    public List<Article> search(String content) {

  42.        return articleService.search(content);

  43.    }

  44.    @RequestMapping(value = "update", method = RequestMethod.POST)

  45.    public long update(long id) {

  46.        return articleService.update(id);

  47.    }

  48. }

Spring Boot的启动类及配置项,这里略过,项目启动后,可能过controller暴露出来的方法进行Article数据索引的CRUD操作




posted @ 2018-01-25 13:13  maventalker  阅读(549)  评论(0编辑  收藏  举报