Elasticsearch整合SpingData

223 阅读4分钟

Elasticsearch整合SpingData

一.概念(倒排索引)

查询疑问:使用Elasticsearch搜索时会发现,有时候搜出来的数据和自己想要的不一样。

因为Elasticsearch引入的分词器,会将字符拆分成不同的词组,而Elasticsearch

查询时引入了倒排索引的一个概念。拆分的词组与之匹配所以会查出一些与词组

匹配的数据。

正排索引:

当查询一条数据时,是依次一条条查按顺序查过去时是正排索引。

倒排索引:

什么是倒排索引,以两句话作为例子:

句1:我想买华为手机 句2:我想买小米手机

第1句话会被分词器拆分为: 1我想买 2华为 3手机

第2句话会被分词器拆分为: 1我想买 2小米 3手机

相同的词语会被的id会被放在一起,当我们查询 “我想买”时

句1,句2话都会被查询出来。

而查询条件为”小米“时 句2会被精确查询出来。

总结为一句话:

不同的话被拆分成不同点词段,当查询到对应的词段,词段会对应与i给id集合,之后将着一些数据查寻出来。

二.准备环境

1.官网地址www.elastic.co/cn/

2.官方文档www.elastic.co/guide/index…

3.Elasticsearch7.8.0的下载地址www.elastic.co/cn/download…

4.Elasticsearch7.8.0的教学文档(136条消息) Elasticsearch学习笔记_巨輪的博客-CSDN博客

三.Elasticsearch

解压后,进入 bin 文件目录,点击 elasticsearch.bat 文件启动 ES 服务 。

注意: 9300 端口为 Elasticsearch 集群间组件的通信端口, 9200 端口为浏览器访问的 http协议 RESTful 端口。

打开浏览器,输入地址: http://localhost:9200,测试返回结果,返回结果如下:

{
  "name" : "DESKTOP-LNJQ0VF",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "nCZqBhfdT1-pw8Yas4QU9w",
  "version" : {
    "number" : "7.8.0",
    "build_flavor" : "default",
    "build_type" : "zip",
    "build_hash" : "757314695644ea9a1dc2fecd26d1a43856725e65",
    "build_date" : "2020-06-14T19:35:50.234439Z",
    "build_snapshot" : false,
    "lucene_version" : "8.5.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

二.使用springData整合Elasticsearch

1.导入依赖

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
			<!--springdata整合elasticsearch的依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
        </dependency>

2.yml

spring:
  application:
    name: es
elasticsearch:
  host: 127.0.0.1  #elasticsearch服务地址 (自定义)
  port: 9200       #elasticsearch服务端口(自定义)

server:
  port: 9000 

3.创建配置类

ElasticsearchRestTemplate是spring-data-elasticsearch项目中的一个类,和其他spring项目中的 template类似。 在新版的spring-data-elasticsearch 中,ElasticsearchRestTemplate 代替了原来的ElasticsearchTemplate。 原因是ElasticsearchTemplate基于TransportClient,TransportClient即将在8.x 以后的版本中移除。所以,我们推荐使用ElasticsearchRestTemplate。 ElasticsearchRestTemplate基于RestHighLevelClient客户端的。需要自定义配置类,继承AbstractElasticsearchConfiguration,并实现elasticsearchClient()抽象方法,创建RestHighLevelClient对象。

package com.example.springdataelasticsearch.config;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;

public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
    @Value("${elasticsearch.host}") 
    private String host ;
    @Value("${elasticsearch.port}")
    private Integer port ;
    //重写父类方法
    @Override
    public RestHighLevelClient elasticsearchClient() {
        RestClientBuilder builder = RestClient.builder(new HttpHost(host, port));
        RestHighLevelClient restHighLevelClient = new
                RestHighLevelClient(builder);
        return restHighLevelClient;
    }

}

4.创建Elasticsearch实体类

package com.example.springdataelasticsearch.es;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
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;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Document(indexName = "shopping",shards = 6,replicas = 1) //shopping 如果索引不存在自动创建
public class ProductEntity {
    @Id
    private Long id;//商品唯一标识

    /**
     * type : 字段数据类型
     * analyzer : 分词器类型
     * index : 是否索引(默认:true)
     * Keyword : 短语,不进行分词
     *	1、ik_max_word
     *  会将文本做最细粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为“中华人民共和国、中华人民、中华、华人、人民共和国、人民、共和国、大会堂、大会、会堂	 *  等词语。
     * 2、ik_smart
     * 会做最粗粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为中华人民共和国、人民大会堂。
     */
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String title;//商品名称

    @Field(type = FieldType.Keyword)
    private String category;//分类名称

    @Field(type = FieldType.Double)
    private Double price;//商品价格

    @Field(type = FieldType.Keyword, index = false)
    private String images;//图片地址

}

5.创建Elasticsearch DAO数据访问对象

package com.example.springdataelasticsearch.dao;

import com.example.springdataelasticsearch.es.ProductEntity;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

public interface ProductDao extends ElasticsearchRepository<ProductEntity, Long> {
}

6.测试集成框架SpirngData

package com.example.springdataelasticsearch;

import com.example.springdataelasticsearch.dao.ProductDao;
import com.example.springdataelasticsearch.es.ProductEntity;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
class SpringDataElasticsearchApplicationTests {
    @Autowired
    private ProductDao productDao;
//    @Autowired
//    private ElasticsearchRestTemplate elasticsearchRestTemplate;
//    @Test
//    void createIndex() {
//        //创建索引,系统初始化会自动创建索引
//        System.out.println();
//    }
//
//    @Test
//    public void deleteIndex(){
//        //创建索引,系统初始化会自动创建索引
//        boolean flg = elasticsearchRestTemplate.deleteIndex(ProductEntity.class);
//        System.out.println("删除索引 = " + flg);
//    }
    @Test
    public void save(){
        ProductEntity product = new ProductEntity();
        product.setId(2L);
        product.setTitle("华为手机");
        product.setCategory("手机");
        product.setPrice(2999.0);
        product.setImages("http://www.atguigu/hw.jpg");
        productDao.save(product);
    }
    //POSTMAN, GET http://localhost:9200/product/_doc/2

    //修改
    @Test
    public void update(){
        ProductEntity product = new ProductEntity();
        product.setId(2L);
        product.setTitle("小米 2 手机");
        product.setCategory("手机");
        product.setPrice(9999.0);
        product.setImages("http://www.atguigu/xm.jpg");
        productDao.save(product);
    }
    //POSTMAN, GET http://localhost:9200/product/_doc/2


    //根据 id 查询
    @Test
    public void findById(){
        ProductEntity product = productDao.findById(2L).get();
        System.out.println(product);
    }

    @Test
    public void findAll(){
        Iterable<ProductEntity> products = productDao.findAll();
        for (ProductEntity product : products) {
            System.out.println(product);
        }
    }

    //删除
    @Test
    public void delete(){
        ProductEntity product = new ProductEntity();
        product.setId(2L);
        productDao.delete(product);
    }
    //POSTMAN, GET http://localhost:9200/product/_doc/2

    //批量新增
    @Test
    public void saveAll(){
        List<ProductEntity> productList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            ProductEntity product = new ProductEntity();
            product.setId(Long.valueOf(i));
            product.setTitle("["+i+"]小米手机");
            product.setCategory("手机");
            product.setPrice(1999.0 + i);
            product.setImages("http://www.atguigu/xm.jpg");
            productList.add(product);
        }
        productDao.saveAll(productList);
    }

    //分页查询
    @Test
    public void findByPageable(){
        //设置排序(排序方式,正序还是倒序,排序的 id)
        Sort sort = Sort.by(Sort.Direction.DESC,"id");
        int currentPage=0;//当前页,第一页从 0 开始, 1 表示第二页
        int pageSize = 5;//每页显示多少条
        //设置查询分页
        PageRequest pageRequest = PageRequest.of(currentPage, pageSize,sort);
        //分页查询
        Page<ProductEntity> productPage = productDao.findAll(pageRequest);
        for (ProductEntity ProductEntity : productPage.getContent()) {
            System.out.println(ProductEntity);
        }
    }

}