【亲测可用】Elesticsearch从入门到精通实例

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 【亲测可用】Elesticsearch从入门到精通实例

写在前面

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于[云计算]中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

可以这样来对比elasticsearch和数据库

索引(indices) ~~~~~~~~ 数据库(databases)

类型(type) ~~~~~~~~ 数据表(table)

文档(Document)~~~~~~~~ 行(row)

字段(Field) ~~~~~~~~ 列(Columns )

shards:分片数量,默认5

replicas:副本数量,默认1

引入库

implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-elasticsearch', version: '2.7.5'
implementation group: 'org.springframework.data', name: 'spring-data-elasticsearch', version: '4.4.17';

版本对应要求见如下表格: 传送门

Spring Data Release Train Spring Data Elasticsearch Elasticsearch Spring Framework Spring Boot
2023.0 (Ullmann) 5.1.x 8.7.1 6.0.x 3.1.x
2022.0 (Turing) 5.0.x 8.5.3 6.0.x 3.0.x
2021.2 (Raj) 4.4.x[1] 7.17.3 5.3.x 2.7.x
2021.1 (Q) 4.3.x[1] 7.15.2 5.3.x 2.6.x
2021.0 (Pascal) 4.2.x[1] 7.12.0 5.3.x 2.5.x
2020.0 (Ockham) 4.1.x[1] 7.9.3 5.3.2 2.4.x
Neumann 4.0.x[1] 7.6.2 5.2.12 2.3.x
Moore 3.2.x[1] 6.8.12 5.2.12 2.2.x
Lovelace 3.1.x[1] 6.2.2 5.1.19 2.1.x
Kay 3.0.x[1] 5.5.0 5.0.13 2.0.x
Ingalls 2.1.x[1] 2.4.0 4.3.25 1.5.x

配置连接

spring:
  elasticsearch:
    rest:
      uris:
        - 10.10.80.162:9200
        - 10.10.80.163:9200
        - 10.10.80.164:9200
      username: root
      password: ********
      timeout: 60000

配置信息读取:

@RefreshScope
@ConfigurationProperties(ESProperties.PREFIX)
public class ESProperties {
    public static final String PREFIX = "spring.elasticsearch.rest";
    private Boolean enable = true;
    private String[] uris;
    private String userName;
    /**
     * Secret key是你账户的密码
     */
    private String password;
  private String deviceId;
  /**请求超时*/
  private long timeout;
    }

连接初始化:

@AutoConfiguration
@EnableConfigurationProperties(ESProperties.class)
@ConditionalOnProperty(value = ESProperties.PREFIX + ".enabled", havingValue = "true", matchIfMissing = true)
public class ElasticSearchConfig extends AbstractElasticsearchConfiguration {
    private static final Logger logger = LogManager.getLogger(ElasticSearchConfig.class);
    @Resource
    private ESProperties esProperties;
    @Override
    @Bean(destroyMethod = "close")
    public RestHighLevelClient elasticsearchClient() {
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(esProperties.getUris())
                .withBasicAuth(esProperties.getUserName(), esProperties.getPassword())
                .withConnectTimeout(RestClientBuilder.DEFAULT_CONNECT_TIMEOUT_MILLIS)
                .withSocketTimeout(esProperties.getTimeout())
                .build();
        RestHighLevelClient client = RestClients.create(clientConfiguration).rest();
        try {
            logger.info("connect to elasticsearch:{} ", client.getLowLevelClient().getNodes());
            MainResponse response = client.info(RequestOptions.DEFAULT);
            MainResponse.Version version = response.getVersion();
            logger.info("elasticsearch version:{},lucene version:{}", version.getNumber(), version.getLuceneVersion());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return client;
    }
}

文件配置 spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=io.gamioo.core.elasticsearch.config.ElasticSearchConfig

DAO层:

public interface OperationLogRepository extends ElasticsearchRepository<OperationLog, String> {
//时间匹配
Page<OperationLog> findByAddTimeBetween(LocalDateTime startTime, LocalDateTime endTime, Pageable pageable);
//字段后匹配
 Page<OperationLog> findByDeviceIdLike(String deviceId, Pageable pageable);
}
//字段前后匹配
 Page<OperationLog> findByDeviceIdContaining(String deviceId, Pageable pageable);
}

更复杂一点的操作

我们可以使用@Query注解进行查询,这样要求我们需要自己写ES的查询语句,需要会ES查询才可以,其实也很简单,不会写查就是了。 看看官方给的例子

public interface OperationLogRepository extends ElasticsearchRepository<OperationLog, String> {
        @Query("{\"bool\" : {\"must\" : {\"field\" : {\"name\" : \"?0\"}}}}")
        Page<OperationLog> findByName(String name,Pageable pageable);
}

操作对象:

@ApiModel(value = "operation_log", description = "操作日志")
@Document(indexName = "operation_log_*")
public class OperationLog {
    @Id
    private String id;
    @ApiModelProperty("名称")
    @Field(name = "name")
    private String name;
    @ApiModelProperty("创建时间")
    @Field(name = "addTime", type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd'T'HH:mm:ssz")
    private Date addTime;
    }

逻辑操作:

@Resource
    private OperationLogRepository repository;
   @Override
    public Page<OperationLog> findAll(Pageable pageable) {
        return repository.findAll(pageable);
    }
    @Override
    public Page<OperationLog> findByAddTimeBetween(LocalDateTime startTime, LocalDateTime endTime, Pageable pageable) {
        return repository.findByAddTimeBetween(startTime, endTime, pageable);
    }

用JPA的话,返回的是整条数据,就会抛出数据量过大的问题,但有时候你只需要部分极少的字段,那时我们就需要自定义EQL进行复杂查询:

public Page<OperationLog> findByAndAddTimeBetweenAndDevUidIn(LocalDateTime startTime, LocalDateTime endTime, List<String> devUid, Pageable pageable) {
        /* 1 查询结果 */
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        // 1.2 source过滤
        builder.withSourceFilter(new FetchSourceFilter(new String[]{"id", "deviceId", "channel", "fileSize"}, new String[0]));
        // 1.3 搜索条件
        BoolQueryBuilder query = QueryBuilders.boolQuery().must(QueryBuilders.termsQuery("deviceId", devUid)).must(QueryBuilders.rangeQuery("created")
                //   .format("yyyy-MM-dd'T'HH:mm:ss.SSSXXXZ")
                //  .format("yyyy-MM-dd HH:mm:ss")
                .timeZone("GMT+8")
                .gte(startTime)
                .lte(endTime)
                .includeLower(true).includeUpper(true));
        //时间范围
        builder.withQuery(query);
        // builder.withQuery(QueryBuilders.matchQuery("title", "手机"));
        // 1.4 分页及排序条件
        builder.withPageable(pageable);
        SearchHits<OperationLog> searchHits = template.search(builder.build(), OperationLog.class);
        List<OperationLog> array = new ArrayList<>();
        for (SearchHit<OperationLog> e : searchHits) {
            array.add(e.getContent());
        }
        return new PageImpl<>(array, pageable, searchHits.getTotalHits());
    }

其中,QueryBuilders是ES中的查询条件构造器

类型 说明
QueryBuilders.boolQuery 子方法must可多条件联查
QueryBuilders.termQuery 精确查询指定字段
QueryBuilders.matchQuery 按分词器进行模糊查询
QueryBuilders.rangeQuery 按指定字段进行区间范围查询

Q&A

1.实际使用中一直报错: missing authentication credentials for REST request

经过多方查证,最后发现报错原因是:配置ES时没添加用户名密码验证

2.org.apache.http.ContentTooLongException: entity content is too long [450975428] for the configured buffer limit [104857600]

3.如何打印ES日志

#es日志
<Logger name="org.springframework.data.elasticsearch.client.WIRE" level="trace" includeLocation="true">
</Logger>

4.NativeSearchQueryBuilder多条件查询,会覆盖前面的条件

// 1.3 搜索条件
query.withQuery(QueryBuilders.termsQuery("devUid", devUid));
//时间范围
query.withQuery(QueryBuilders.rangeQuery("created")
                .format("yyyy-MM-dd'T'HH:mm:ssz")
                .timeZone("GMT+8")
                .gte(startTime)
                .lte(endTime)
                .includeLower(true).includeUpper(true));

调用了多个withQuery,通过底层的代码可以看出会覆盖前面withQuery,只保留一个withQuery,因为源码实现这样的,

public NativeSearchQueryBuilder withQuery(QueryBuilder queryBuilder) {
    this.queryBuilder = queryBuilder;
    return this;
  }

所以得改成如下:

BoolQueryBuilder query = QueryBuilders.boolQuery().must(QueryBuilders.termsQuery("devUid", devUid)).must(QueryBuilders.rangeQuery("created")
                .format("yyyy-MM-dd'T'HH:mm:ssz")
                .timeZone("GMT+8")
                .gte(startTime)
                .lte(endTime)
                .includeLower(true).includeUpper(true));
        //时间范围
        builder.withQuery(query);
  1. Jet Brains DataGrip 连接到 Elasticsearch 目前指定的版本或许可以连上,但自己定义的版本却连不上,有谁可以帮我?

    驱动下载地址为:https://www.elastic.co/cn/downloads/jdbc-client

总结

以上就是springboot集成es后的一个简单使用,spring封装过后的spring-boot-starter-data-elasticsearch使用起来还是非常方便简单的。

JPA自带的这些方法肯定是不能满足我们的业务需求的,那么我们如何自定义方法呢?我们只要使用特定的单词对方法名进行定义,那么Spring就会对我们写的方法名进行解析, 生成对应的实例进行数据处理,有木有很简单?那么接下来就使用Spring官方文档中的实例进行演示,先来看下关键字的说明

附上JPA操作的表:

关键字 使用示例 等同于的ES查询
And findByNameAndPrice {“bool” : {“must” : [ {“field” : {“name” : “?”}}, {“field” : {“price” : “?”}} ]}}
Or findByNameOrPrice {“bool” : {“should” : [ {“field” : {“name” : “?”}}, {“field” : {“price” : “?”}} ]}}
Is findByName {“bool” : {“must” : {“field” : {“name” : “?”}}}}
Not findByNameNot {“bool” : {“must_not” : {“field” : {“name” : “?”}}}}
Between findByPriceBetween {“bool” : {“must” : {“range” : {“price” : {“from” : ?,“to” : ?,“include_lower” : true,“include_upper” : true}}}}}
LessThanEqual findByPriceLessThan {“bool” : {“must” : {“range” : {“price” : {“from” : null,“to” : ?,“include_lower” : true,“include_upper” : true}}}}}
GreaterThanEqual findByPriceGreaterThan {“bool” : {“must” : {“range” : {“price” : {“from” : ?,“to” : null,“include_lower” : true,“include_upper” : true}}}}}
Before findByPriceBefore {“bool” : {“must” : {“range” : {“price” : {“from” : null,“to” : ?,“include_lower” : true,“include_upper” : true}}}}}
After findByPriceAfter {“bool” : {“must” : {“range” : {“price” : {“from” : ?,“to” : null,“include_lower” : true,“include_upper” : true}}}}}
Like findByNameLike {“bool” : {“must” : {“field” : {“name” : {“query” : “? *”,“analyze_wildcard” : true}}}}}
StartingWith findByNameStartingWith {“bool” : {“must” : {“field” : {“name” : {“query” : “? *”,“analyze_wildcard” : true}}}}}
EndingWith findByNameEndingWith {“bool” : {“must” : {“field” : {“name” : {“query” : “*?”,“analyze_wildcard” : true}}}}}
Contains/Containing findByNameContaining {“bool” : {“must” : {“field” : {“name” : {“query” : “?”,“analyze_wildcard” : true}}}}}
In findByNameIn(Collectionnames) {“bool” : {“must” : {“bool” : {“should” : [ {“field” : {“name” : “?”}}, {“field” : {“name” : “?”}} ]}}}}
NotIn findByNameNotIn(Collectionnames) {“bool” : {“must_not” : {“bool” : {“should” : {“field” : {“name” : “?”}}}}}}
True findByAvailableTrue {“bool” : {“must” : {“field” : {“available” : true}}}}
False findByAvailableFalse {“bool” : {“must” : {“field” : {“available” : false}}}}
OrderBy findByAvailableTrueOrderByNameDesc {“sort” : [{ “name” : {“order” : “desc”} }],“bool” : {“must” : {“field” : {“available” : true}}}}

参考:

ElasticSearch与SpringBoot的集成与JPA方法的使用

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
目录
相关文章
|
6月前
|
搜索推荐 关系型数据库 MySQL
手把手教你搭建子比主题的系统(亲测可用)|学习版本|虚拟知识付费平台比较合适
搭建Zibll子比主题涉及以下步骤: 1. 服务器环境需支持PHP 7.0+(推荐7.4+)和MySQL。 2. 下载并安装WordPress,可从官方站点获取最新版本。 3. 从指定链接下载子比主题文件。 4. 在WordPress后台上传并启用子比主题,配置固定链接和伪静态,例如使用宝塔面板。 5. 调整主题设置,如Logo和网站关键词。 6. 安装必要插件,如Yoast SEO和Contact Form 7,根据实际需求选择。 7. 完成后测试和调试网站功能。 记得参考官方文档以获取详细指导。
|
6月前
|
Linux 虚拟化 开发者
图解虚拟机安装步骤(超详细教程)
图解虚拟机安装步骤(超详细教程)
127 0
|
12月前
|
Kubernetes 安全 Docker
k8s教程(基础篇)-安装与配置概述
k8s教程(基础篇)-安装与配置概述
371 0
|
12月前
|
小程序 前端开发 JavaScript
【小程序】注册安装及创建小程序---入门级别必读
【小程序】注册安装及创建小程序---入门级别必读
142 0
|
前端开发 JavaScript
electron入门(16.0版本亲测可用)
electron入门全记录,亲测可用
149 1
|
存储 并行计算 测试技术
【CUDA学习笔记】第五篇:内存以及案例解释(附案例代码下载方式)(二)
【CUDA学习笔记】第五篇:内存以及案例解释(附案例代码下载方式)(二)
168 0
【CUDA学习笔记】第五篇:内存以及案例解释(附案例代码下载方式)(二)
|
存储 并行计算 计算机视觉
【CUDA学习笔记】第五篇:内存以及案例解释(附案例代码下载方式)(一)
【CUDA学习笔记】第五篇:内存以及案例解释(附案例代码下载方式)(一)
290 0
QtSingleApplication 实现单例模式 【实际项目,亲测可用哈】
QtSingleApplication 实现单例模式 【实际项目,亲测可用哈】
QtSingleApplication 实现单例模式 【实际项目,亲测可用哈】
|
Linux 数据安全/隐私保护 开发者
默认配置单机版演示|学习笔记
快速学习默认配置单机版演示。
默认配置单机版演示|学习笔记
|
Java Linux 数据安全/隐私保护
默认配置单机版演示 | 学习笔记
快速学习默认配置单机版演示
107 0
默认配置单机版演示 | 学习笔记