欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Data ElasticSearch的使用

程序员文章站 2022-07-04 23:41:31
...

1.spring Data ElasticSearch 简介

1.1 什么是Spring Data

Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快
捷,并支持map-reduce框架和云计算数据服务。 Spring Data可以极大的简化JPA的写法,可以在几乎不用写实现
的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等一些常用的功能。
Spring Data的官网:http://projects.spring.io/spring-data/

1.2什么是Spring Data ElasticSearch

Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API
进行封装 。Spring Data为Elasticsearch项目提供集成搜索引擎。Spring Data Elasticsearch POJO的关键功能区域
为中心的模型与Elastichsearch交互文档和轻松地编写一个存储库数据访问层。
官方网站:http://projects.spring.io/spring-data-elasticsearch/

2 Spring Data ElasticSearch入门

步骤分析

  • 工程搭建
    • 创建一个java工程
    • 把相关jar包添加到工程中,如果是maven工程就添加坐标
    • 配置一个spring的配置文件
      • 配置elasticsearch:transport-client
      • elasticsearch:repositories:包扫描器,扫描dao的接口
      • 配置elasticsearchTemplate对象,对象就是一个bean
  • 管理索引库
    • 创建一个Entity类,其实就是一个javabean(pojo),映射到一个文档上
      需要添加一些注解进行标注
    • 创建一个dao接口,需要继承ElasticSearchRepository接口
    • 编写测试代码

2.1 jar包的导入

<dependencies>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>5.6.8</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>transport</artifactId>
            <version>5.6.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-to-slf4j</artifactId>
            <version>2.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.24</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.21</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.8.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.8.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.8.1</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>3.0.5.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>org.elasticsearch.plugin</groupId>
                    <artifactId>transport-netty4-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.4.RELEASE</version>
        </dependency>

    </dependencies>

2.2 创建applicationContext.xml配置文件,引入elasticsearch命名空间

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
       xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/data/elasticsearch
		http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd
		">

    <!-- Client客户端配置 -->
    <elasticsearch:transport-client id="esClient"
                                    cluster-name="my-elasticsearch" cluster-nodes="127.0.0.1:9301,127.0.0.1:9302,127.0.0.1:9303" />

    <!-- 配置包扫描器,扫描dao的接口 -->
    <elasticsearch:repositories base-package="com.cui.es.repositories"/>
    <!-- ElasticSearch模版对象  -->
    <bean id="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
        <constructor-arg name="client" ref="esClient"/>
    </bean>
</beans>

2.3编写实体Article

public class Article {

    private Integer id;
    private String title;
    private String content;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    @Override
    public String toString() {
        return "Article [id=" + id + ", title=" + title + ", content=" + content + "]";
    }

}

2.4配置实体类

package com.cui.es.entity;

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

//@Document 文档对象 (索引信息、文档类型 )
@Document(indexName="blog3",type="article")
public class Article {

    //@Id 文档主键 唯一标识
    @Id
    //@Field 每个文档的字段配置(类型、是否分词、是否存储、分词器 )
    @Field(store=true, index = false,type = FieldType.Integer)
    private Integer id;
    @Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type = FieldType.text)
    private String title;
    @Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type = FieldType.text)
    private String content;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    @Override
    public String toString() {
        return "Article [id=" + id + ", title=" + title + ", content=" + content + "]";
    }
}
其中,注解解释如下:
@Document(indexName="blob3",type="article"):
    indexName:索引的名称(必填项)
    type:索引的类型
@Id:主键的唯一标识
@Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type = FieldType.text)
    index:是否设置分词
    analyzer:存储时使用的分词器
    searchAnalyze:搜索时使用的分词器
    store:是否存储
    type: 数据类型

2.5编写dao层

package com.cui.es.repositories;

import com.cui.es.entity.Article;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

/**
 * @创建人 cxp
 * @创建时间 2019-10-8
 * @描述
 */
public interface ArticleRepository extends ElasticsearchRepository<Article,Long> {
}

3.配置测试类,开始curd操作

3.1测试添加索引

  • 步骤分析
    • 直接使用ElasticSearchTemplate对象的createIndex方法创建索引,并设置映射关系
  • 代码实现
import com.cui.es.entity.Article;
import com.cui.es.repositories.ArticleRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataElasticSearchTest {

    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private ElasticsearchTemplate templatet;


    //创建索引库
    @Test
    public void createIndex()throws Exception{
        //创建索引,并配置映射关系
        templatet.createIndex(Article.class);
    }
}

3.2 测试添加文档

  • 步骤分析
    • 创建一个Article对象
    • 使用ArticleRepository对象中的添加方法
  • 代码实现
import com.cui.es.entity.Article;
import com.cui.es.repositories.ArticleRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataElasticSearchTest {

    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private ElasticsearchTemplate templatet;

    //添加文档
    @Test
    public void addDocument(){
        //创建一个Article对象
        Article article = new Article();
        article.setId(1l);
        article.setTitle("“中国的昨天已经写在人类的史册上,中国的今天正在亿万人民手中创造,中国的明天必将更加美好。");
        article.setContent("不忘初心、牢记使命");
        //把文档写入索引库
        articleRepository.save(article);
    }
 }

3.3 测试删除文档

  • 步骤分析
    • 使用ArticleRepository对象中的添加方法
  • 代码实现
import com.cui.es.entity.Article;
import com.cui.es.repositories.ArticleRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataElasticSearchTest {

    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private ElasticsearchTemplate templatet;
    //删除文档
    @Test
    public void deleteDocument(){
        //删除所有文档
        //articleRepository.deleteAll();
        //根据id删除文档
        articleRepository.deleteById(2l);
    }
}    

3.4测试更新文档

  • 原理:
    • 因为Es是基于Lucene的,所以更新文档就是先删除文档在新建文档

3.5文档的几种查询方法

3.5.1 SpringDataES的简单查询
  • 步骤分析
    • 直接使用ArticleRepository对象中的添加方法
  • 代码实现
import com.cui.es.entity.Article;
import com.cui.es.repositories.ArticleRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.Optional;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataElasticSearchTest {

   @Autowired
   private ArticleRepository articleRepository;

   @Autowired
   private ElasticsearchTemplate templatet;


   //查询文档
   @Test
   public void findArticle() throws Exception{
       //查找所有文档
       Iterable<Article> articles = articleRepository.findAll();
       //lambda表达式
       articles.forEach(a-> System.out.println(a));
       //根据id查询文档
       Optional<Article> optional = articleRepository.findById(1l);
       Article article = optional.get();
       System.out.println(article);
   }
  }
3.5.2自定义查询方式
  • 注意:*如果不设置分页信息,默认带分页,每页显示10条数据 *
  • 如果设置分页信息,应该在方法中添加一个参数Pageable
  • Pageable pageable =PageRequest.of(0,n);
  • PS:设置分页信息,默认从0页开始
  • 可以对搜索的内容先分词在进行查询,每个词之间都是and的关系
    • 代码实现
package com.cui.es.repositories;

import com.cui.es.entity.Article;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

/**
 * @创建人 cxp
 * @创建时间 2019-10-8
 * @描述
 */
public interface ArticleRepository extends ElasticsearchRepository<Article,Long> {

    //根据标题查询
    List<Article> findByTitle(String title);
    //根据title或者content
    List<Article> findByTitleOrContent(String title,String content);
    //设置分页信息,默认从0页开始
    List<Article> findByTitleOrContent(String title, String content, Pageable pageable);
}
import com.cui.es.entity.Article;
import com.cui.es.repositories.ArticleRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;
import java.util.Optional;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataElasticSearchTest {

    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private ElasticsearchTemplate templatet;


    //自定义查询方式
    @Test
    public void testFindByIdOrContentPage(){
        PageRequest pageable = PageRequest.of(0, 18);
        List<Article> list = articleRepository.findByTitleOrContent("好好", "不忘",pageable);
        list.stream().forEach(a-> System.out.println(a));
    }

    @Test
    public void testFindByIdOrContent(){
        List<Article> list = articleRepository.findByTitleOrContent("好好", "不忘");
        list.stream().forEach(a-> System.out.println(a));
    }

    @Test
    public void testFindByTitle(){
        List<Article> list = articleRepository.findByTitle("好好");
        list.stream().forEach(a-> System.out.println(a));
    }
}
3.6使用原生查询条件查询
  • NativeSearcchQuery对象
  • 使用方法:
    • 创建一个NativeSearchQuery对象
      • 设置查询条件,QueryBuilder对象
    • 使用ElasticSearchTemplate对象执行查询
    • 取得查询结果
  • 代码实现
import com.cui.es.entity.Article;
import com.cui.es.repositories.ArticleRepository;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;
import java.util.Optional;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataElasticSearchTest {

    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private ElasticsearchTemplate templatet;


    @Test
    public void testNativeSearchQuery() throws Exception{
        //创建一个查询对象
        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.queryStringQuery("我们都要好好的").defaultField("title"))
                .withPageable(PageRequest.of(0, 15))
                .build();
        //执行查询
        List<Article> articles = templatet.queryForList(query, Article.class);
        articles.stream().forEach(a-> System.out.println(a));
    }
}