项目中使用es(一):使用springboot操作elasticsearch

这篇具有很好参考价值的文章主要介绍了项目中使用es(一):使用springboot操作elasticsearch。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

对于elasticsearch的搭建,前面写了一篇文章有简单描述如何搭建es,本次主要介绍如何在项目里使用,主要使用ElasticsearchRepository和ElasticsearchRestTemplate操作es。

搭建项目环境和选择合适版本

首先选择合适的项目组件版本,因为es版本和springboot版本有对应,如果不合适会报错。
这里以es7.6.x版本、springboot2.7.12,java8、maven3.8写出来的demo。
首先引入maven

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.7.12</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

主要还是第一个dependency配置,就是操作es的。

具体的代码实现(1)继承ProductInfoRepository

1.config类,主要用于配置扫描操作es所用的repository

@Configuration
@EnableElasticsearchRepositories(basePackages = "com.es.demo.repository")
public class ElasticsearchConfig {
}

2.对应的实体类ProductInfo

@Data
@Document(indexName = "product-info")
public class ProductInfo implements Serializable {

    @Id
    private Integer id;
    @Field(type = FieldType.Text, searchAnalyzer = "ik_max_word", analyzer = "ik_smart")
    private String productName;
    @Field(type = FieldType.Text, searchAnalyzer = "ik_max_word", analyzer = "ik_smart")
    private String description;
    @Field(type = FieldType.Keyword)
    private Date createTime;
    @Field(type = FieldType.Keyword)
    private BigDecimal price;
    @Field(type = FieldType.Integer)
    private Integer num;

}

3.创建repository包,这里防止所有的es对应的索引操作类。所有类继承org.springframework.data.elasticsearch.repository.ElasticsearchRepository,这里以ProductInfo为例:

@Component
public interface ProductInfoRepository extends ElasticsearchRepository<ProductInfo, Integer> {
}

第一个泛型是操作的索引类,第二个是唯一标识(id)对应的类型,
在这个类里按照一定的规则可以直接写一些方法名,不用写实现,ElasticsearchRepository会自动帮我们实现。具体我没有写,你们可以去网上搜一下怎么写。

4.因为ProductInfoRepository中实现了基本的增删改查,所以在这里可以直接使用
项目中使用es(一):使用springboot操作elasticsearch
如何使用:

public class ProductServiceImpl implements ProductService {
    @Autowired
    private ProductInfoRepository productInfoRepository;

    @Override
    public Boolean save(ProductInfo... productInfo) {
        productInfoRepository.saveAll(Arrays.asList(productInfo));
        return true;
    }

    @Override
    public Boolean delete(Integer id) {
        productInfoRepository.deleteById(id);
        return null;
    }

    @Override
    public ProductInfo getById(Integer id) {
        Optional<ProductInfo> byId = productInfoRepository.findById(id);
        return byId.orElse(null);
    }

    @Override
    public List<ProductInfo> getAll() {
        List<ProductInfo> list = new ArrayList<>();
        productInfoRepository.findAll().forEach(list::add);
        return list;
    }

具体的代码实现(2)使用ElasticsearchRestTemplate操作

1.对于一些复杂的查询我是直接使用ElasticsearchRestTemplate这个类来操作的。写了一个公共类,类似mybatisplus的service抽象,具体service接口和实现类可以直接继承。也是看别的开源项目这么写自己总结出来的。
首先是接口层BasicEsService:


public interface BasicEsService<T> {

    /**
     * 保存数据
     *
     * @param indexEnum 索引
     * @param ts        数据
     */
    void save(IndexEnum indexEnum, T... ts);

    /**
     * 删除数据
     *
     * @param indexEnum 索引
     * @param id        id
     */
    void delete(IndexEnum indexEnum, String id);

    /**
     * 查询单个数据
     *
     * @param indexEnum
     * @param id
     * @param clazz
     * @return
     */
    T getById(IndexEnum indexEnum, String id, T clazz);

    /**
     * 查询所有数据,es限制最多返回10000条
     *
     * @param indexEnum
     * @param clazz
     * @return
     */
    List<T> getAllData(IndexEnum indexEnum, T clazz);

    /**
     * 动态sql查询
     *
     * @param sql
     * @param clazz
     * @return
     */
    List<Map<String, Object>> query(String sql, T clazz);

    /**
     * 范围查询
     *
     * @param pageNo
     * @param pageSize
     * @param indexEnum
     * @param order
     * @param rangeParam
     * @return
     */
    Page<T> rangeQuery(Integer pageNo, Integer pageSize, IndexEnum indexEnum, Map<String, String> order, Map<String, Object[]> rangeParam, T clazz);

    /**
     * 分页查询,默认十条,支持多字段模糊匹配,多字段排序
     *
     * @param pageNo   从0开始
     * @param pageSize 每页记录数
     * @param keyword  关键词
     * @param clazz    转换的对象
     * @param order    排序集合
     * @param fields   搜索的列
     * @return
     */
    Page<T> pageList(Integer pageNo, Integer pageSize, String keyword, T clazz, Map<String, String> order, String... fields);

然后是实现类BasicEsServiceImpl


@Service
public class BasicEsServiceImpl<T> implements BasicEsService<T> {

    @Autowired
    protected ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public void save(IndexEnum indexEnum, T... ts) {
        T[] save = elasticsearchRestTemplate.save(ts, IndexCoordinates.of(indexEnum.getIndex()));
        return;
    }
    @Override
    public void delete(IndexEnum indexEnum, String id) {
        String delete = elasticsearchRestTemplate.delete(id, IndexCoordinates.of(indexEnum.getIndex()));
    }
    @Override
    public T getById(IndexEnum indexEnum, String id, T clazz) {
        elasticsearchRestTemplate.get(id, clazz.getClass(), IndexCoordinates.of(indexEnum.getIndex()));
        return null;
    }
    @Override
    public List<T> getAllData(IndexEnum indexEnum, T clazz) {
        Query query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchAllQuery()).build();
        SearchHits<T> searchHits = (SearchHits<T>) elasticsearchRestTemplate.search(query, clazz.getClass(), IndexCoordinates.of(indexEnum.getIndex()));
        return searchHits.get().map(SearchHit::getContent).collect(Collectors.toList());
    }
    @Override
    public List<Map<String, Object>> query(String sql, T clazz) {
        throw new AbstractMethodError();
    }
    @Override
    public Page<T> rangeQuery(Integer pageNo, Integer pageSize, IndexEnum indexEnum, Map<String, String> order, Map<String, Object[]> rangeParam, T clazz) {
        //范围查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        rangeParam.keySet().forEach(field -> {
            boolQueryBuilder.must(new RangeQueryBuilder(field).gt(rangeParam.get(field)[0]).lt(rangeParam.get(field)[1]));
        });
        PageRequest of = PageRequest.of(pageNo, pageSize);
        List<FieldSortBuilder> sortBuilderList = order.keySet().stream()
                .map(field -> SortBuilders.fieldSort(field).order(SortOrder.valueOf(order.get(field))))
                .collect(Collectors.toList());
        Query searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withPageable(of)
                .withSorts((SortBuilder<?>) sortBuilderList)
                .build();
        SearchHits<T> searchHits = (SearchHits<T>) elasticsearchRestTemplate.search(searchQuery, clazz.getClass());
        SearchPage<T> searchHits1 = SearchHitSupport.searchPageFor(searchHits, searchQuery.getPageable());
        return new PageImpl<>(searchHits.get().map(SearchHit::getContent).collect(Collectors.toList()), searchHits1.getPageable(), searchHits1.getTotalElements());
    }
    @Override
    public Page<T> pageList(Integer pageNo, Integer pageSize, String keyword, T clazz, Map<String, String> order, String... fields) {
        //分页,页码从0开始
        PageRequest of = PageRequest.of(pageNo, pageSize);
        List<FieldSortBuilder> collect = order.keySet().stream()
                .map(field -> SortBuilders.fieldSort(field).order(SortOrder.valueOf(order.get(field))))
                .collect(Collectors.toList());

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        Arrays.asList(fields).forEach(e -> boolQueryBuilder.should(QueryBuilders.fuzzyQuery(e, keyword)));
        Query searchQuery = new NativeSearchQueryBuilder()
                //条件
                .withQuery(boolQueryBuilder)
                //分页
                .withPageable(of)
                //排序
                .withSorts((SortBuilder<?>) collect)
                .build();
        SearchHits<T> searchHits = (SearchHits<T>) elasticsearchRestTemplate.search(searchQuery, clazz.getClass());
        SearchPage<T> searchHits1 = SearchHitSupport.searchPageFor(searchHits, searchQuery.getPageable());
        return new PageImpl<>(searchHits.get().map(SearchHit::getContent).collect(Collectors.toList()), searchHits1.getPageable(), searchHits1.getTotalElements());
    }
}

因为ElasticsearchRestTemplate这个操作需要传入具体的索引名称,所以我创建了一个公共枚举类存放es索引名称
IndexEnum

@Getter
@AllArgsConstructor
public enum IndexEnum {

    PRODUCT_INFO("product-info", "_doc");

    private String index;
    private String type;
}

使用的话就直接继承就行了
接口层

public interface ProductService extends BasicEsService<ProductInfo>{
}

实现层

@Service
@Slf4j
public class ProductServiceImpl extends BasicEsServiceImpl<ProductInfo> implements ProductService {
}

后面如果有公共的方法也可以抽出来放在公共类里。

问题总结

1.问题1:启动报错org.elasticsearch.client.ResponseException: method [PUT], host [http://10.0.180.100:9200], URI [/productInfo], status line [HTTP/1.1 406 Not Acceptable]

org.elasticsearch.client.ResponseException: method [PUT], host [http://10.0.180.100:9200], URI [/productInfo], status line [HTTP/1.1 406 Not Acceptable]

这是因为springboot和es版本不对应导致的,我最开始用的是springboot3和es7.6,后来把springboot版本降到了2.7.x。

问题2:“type”:“invalid_index_name_exception”

org.elasticsearch.client.ResponseException: method [PUT], host [http://10.0.180.100:9200], URI [/productInfo?master_timeout=30s&timeout=30s], status line [HTTP/1.1 400 Bad Request]
{"error":{"root_cause":[{"type":"invalid_index_name_exception","reason":"Invalid index name [productInfo], must be lowercase","index_uuid":"_na_","index":"productInfo"}],"type":"invalid_index_name_exception","reason":"Invalid index name [productInfo], must be lowercase","index_uuid":"_na_","index":"productInfo"},"status":400}

这是因为我索引名称用了大写字母,而es规定索引名称不能使用大写,所以修改配置
@Document(indexName = “productInfo”),替换成了@Document(indexName = “product-info”)

最后放个demo

最后在放一个我写的demo地址,有兴趣可以看下
https://gitee.com/wdvc/es-demo.git
唉,就这样吧,如果有问题请指出来我马上修改文章来源地址https://www.toymoban.com/news/detail-478488.html

到了这里,关于项目中使用es(一):使用springboot操作elasticsearch的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ElasticSearch保姆级教程[1]——SpringBoot 项目中使用 ES

    该教程主要分为 三篇文章。此为第一篇——主要介绍 ElasticSearch、Kibana 的安装 以及如何 通过 Http 和Java API的方式使用 ElasticSearch。学完本文,你就可以 在SpringBoot 项目中使用 ES了。第二篇超链接、第三篇超链接 一、实现ElasticSearch 单机运行 1.1 安装运行ElasticSearch 首先,我们

    2023年04月10日
    浏览(42)
  • ES完整使用从安装到springboot项目操作

    1. ES的原理和基本概念 ES一般使用保存日志数据,对数据做日志做一些管理,ElasticSearch(resful风格)数据只有json类型的, ElastricSearch和Solr都是基于 Lucene 的全文搜索引擎服务器 Lucene: apache的子项目开源的全文搜索引擎工具包 倒排索引: 通过term或者说某个词记录其所在的文档

    2024年02月12日
    浏览(53)
  • springboot操作ES之ElasticSearch_EasyEs

    前置环境 es:7.x springboot:2.6.0 easyes:1.0.2 1.导入依赖 2.配置文件 3.新建实体类 Document Comment User 4.启动类上面加EsMapperScan 5.最后测试各种操作

    2024年02月12日
    浏览(45)
  • Java SpringBoot API 实现ES(Elasticsearch)搜索引擎的一系列操作(超详细)(模拟数据库操作)

    小编使用的是elasticsearch-7.3.2 基础说明: 启动:进入elasticsearch-7.3.2/bin目录,双击elasticsearch.bat进行启动,当出现一下界面说明,启动成功。也可以访问http://localhost:9200/ 启动ES管理:进入elasticsearch-head-master文件夹,然后进入cmd命令界面,输入npm run start 即可启动。访问http

    2024年02月04日
    浏览(57)
  • spring boot 项目中搭建 ElasticSearch 中间件 一 postman 操作 es

    作者: 逍遥Sean 简介:一个主修Java的Web网站游戏服务器后端开发者 主页:https://blog.csdn.net/Ureliable 觉得博主文章不错的话,可以三连支持一下~ 如有需要我的支持,请私信或评论留言! 本文是ElasticSearch 的入门文章,包含ElasticSearch 的环境准备和基础操作(使用postman) Elas

    2024年02月11日
    浏览(36)
  • spring boot 项目中搭建 ElasticSearch 中间件 一 spring data 操作 es

    作者: 逍遥Sean 简介:一个主修Java的Web网站游戏服务器后端开发者 主页:https://blog.csdn.net/Ureliable 觉得博主文章不错的话,可以三连支持一下~ 如有需要我的支持,请私信或评论留言! 本文是进行ElasticSearch 的环境准备和基础操作(使用postman),并且已经能够使用java api操作

    2024年02月10日
    浏览(44)
  • 18、全文检索--Elasticsearch-- SpringBoot 整合 Spring Data Elasticsearch(异步方式(Reactive)和 传统同步方式 分别操作ES的代码演示)

    启动命令行窗口,执行:elasticsearch 命令即可启动 Elasticsearch 服务器 三种查询方式解释: 方法名查询: 就是全自动查询,只要按照规则来定义查询方法 ,Spring Data Elasticsearch 就会帮我们生成对应的查询语句,并且生成方法体。 @Query 查询 : 就是半自动查询, 按照 S

    2024年03月12日
    浏览(67)
  • Elasticsearch学习3-使用RestClient操作es

    JavaREST客户端有两种模式: Java Low Level REST Client:ES官方的低级客户端。低级别的客户端通过http与Elasticearch集群通信。 Java High Level REST Client:ES官方的高级客户端。基于上面的低级客户端,也是通过HTTP与ES集群进行通信。它提供了更多的接口。 此外Spring也对RestClient进行了封装

    2024年02月11日
    浏览(47)
  • 【Elasticsearch】使用Python完成对ES的插入操作

    1.Python搭建Flask服务,编写ES脚本。 2.通过Java调用Python接口,完成对ES的插入操作。 Elasticsearch 7.16.0 ESObject是一个模板,其中有很多其他的函数。通过Java调用,还可以实现很多操作,如删除、查询等。

    2024年02月15日
    浏览(43)
  • 使用postman和es插件操作elasticsearch API

    本文介绍了使用postman和es浏览器插件操作elasticsearch API的常用方法 本文使用的es浏览器插件时edge下的elasticvue,可以在edge的应用商店直接搜索安装,相较于es-head,这个插件一直在维护更新,使用还是很方便的     查看索引 查看索引主要使用get方法,可以查看单个or多个索引,

    2024年02月07日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包