EelasticSearch

EelasticSearch是什么?

1.概述

Elasticsearch 是一个基于 Apache Lucene 构建的开源分布式搜索引擎和分析引擎。它专为云计算环境设计,提供了一个分布式的、高可用的实时分析和搜索平台。Elasticsearch 可以处理大量数据,并且具备横向扩展能力,能够通过增加更多的硬件资源来应对数据和查询量的增长。

Elasticsearch 的核心特点包括:

  1. 全文搜索:支持对各种类型的数据(包括结构化、半结构化和非结构化文本数据)进行快速高效的全文本搜索。

  2. 分布式:数据在集群中的多个节点间分布和复制,确保高可用性和容错性,同时也支持水平扩展,以应对更大的数据量和更高的并发访问。

  3. 实时性:数据一旦写入 Elasticsearch,几乎可以立即被搜索到,提供近乎实时的搜索体验。

  4. 分析能力:内置丰富的数据分析工具,包括聚合分析(Aggregations)和其他统计功能,便于用户对数据进行深入挖掘和洞察。

  5. 多租户:支持索引级别的隔离,每个索引可以配置分片数量和副本数量,以满足不同业务场景的需求。

  6. RESTful API:通过 HTTP/HTTPS 协议提供 JSON 格式的 REST API 接口,易于与其他系统集成,支持多种开发语言调用。

  7. 灵活的文档模型:无需预定义严格的表结构,而是采用动态 schema 或映射,可以根据文档内容自动识别数据类型和结构。

Elasticsearch 被广泛应用在日志分析、监测数据、企业搜索、电子商务搜索、实时分析等多个领域,并常与 Logstash(日志收集和处理工具)、Kibana(数据可视化平台)共同构成 Elastic Stack(原 ELK Stack),形成一套完整的日志管理和数据分析解决方案。

2.什么场景会用到Elasticsearch

  1. 全文搜索

  2. 电商搜索:快速查找商品信息,支持模糊匹配、关键词高亮显示、过滤、排序等功能。

  3. 站内搜索:网站内部的页面、文章、博客等内容的搜索,提供类似Google的搜索体验。

  4. 文档管理系统:企业级文档搜索,如办公文档、合同、法律文件等的高效检索。

  5. 论坛和社交媒体:用户发表的内容搜索,如帖子、评论、话题等。

  6. 日志分析与监控

  7. 服务器日志:收集、索引和分析服务器产生的各类日志,用于故障排查、性能优化、安全审计等。

  8. 应用日志:跟踪应用程序的行为,帮助开发人员迅速定位错误、诊断问题。

  9. 运维监控:收集系统指标、网络流量数据,实时或历史数据分析,可视化展示系统状态和趋势。

  10. 数据分析

  11. 业务分析:实时或批量分析业务数据,生成报表,进行趋势分析、关联分析等。

  12. 时序数据分析:存储和分析时间序列数据,例如设备传感器数据、用户行为数据等。

  13. NoSQL JSON文档数据库

  14. 作为JSON文档数据库使用,存储和检索半结构化数据,支持地理位置查询和混合查询。

  15. 搜索推荐

  16. 实现个性化搜索和推荐功能,根据用户的搜索历史和行为模式,智能推荐相关内容。

  17. 地理信息系统

  18. 存储和查询带有地理位置信息的数据,构建地图应用、位置服务等相关功能。

  19. 大规模监控系统

  20. 结合Logstash和Kibana,搭建ELK Stack,进行大规模分布式环境下的日志集中管理、实时分析和可视化展示。

总之,Elasticsearch 适合那些需要对大量数据进行快速检索、实时分析和可视化展现的应用场景,特别是在处理非结构化或半结构化数据方面表现尤为出色。随着功能的不断丰富和完善,Elasticsearch 已经成为现代数据驱动型企业不可或缺的基础架构组件之一。

EelasticSearch安装

1.Docker安装

docker run -d --name es7 -e ES_JAVA_POTS="-Xms256m -Xmx256m" -e "discovery.type=single-node" -v /opt/es7/data/:/usr/share/elasticsearch/data  -p 9200:9200 -p 9300:9300 elasticsearch:7.14.0

2.客户端UI工具,Edge浏览器扩展

3.分词器安装

3.1为什么要安装分词器?

在 Elasticsearch 的 IK Analyzer 中,ik_smartik_max_word 是IK 分词器针对中文分词提供的两种策略,但分词效果和粒度不同:

ik_smart: 这种模式更侧重于保持语义完整性,尽量进行较少的、更有意义的拆分,减少无意义的子词组合,提高搜索准确率,降低误报率。

示例:“中华人民共和国人民大会堂” 分词结果(ik_smart)可能只有:“中华人民共和国”、“人民大会堂”等较完整、更具实际意义的词语组合。

ik_max_word: 此模式致力于最大化地拆分文本,即尽可能多地生成可能的词语组合,包括单字、双字直至整个短语。它的特点是尽力穷举所有可能的词汇,提高召回率,但在某些情况下可能会造成噪声较多。

示例:“中华人民共和国人民大会堂” 分词结果(ik_max_word)可能包括:中华人民共和国、中华人民、中华、华人、人民共和国、人民、共和国、大会堂、大会、会堂等。

简单来说,ik_max_word 更倾向于全面细致的分词,而 ik_smart 则偏向于精简和精准的分词。在实际应用场景中,选择哪种模式取决于项目的具体需求,如是否需要扩大搜索覆盖面还是提高搜索准确性。

3.2安装

参考网址:https://blog.51cto.com/u_15116285/6100979

官方插件下载地址:

https://github.com/medcl/elasticsearch-analysis-ik/releases

#第一步 copy 插件到容器
docker cp /opt/es7/elasticsearch-analysis-ik-7.14.0.zip 容器id:/usr/share/elasticsearch

#第二步进入你的容器
docker exec -it 容器id /bin/bash
若没有权限执行以下语句
chomd 777 ./data

#第三步执行如下命令,安装插件,中间会提示 Y or N,直接写 Y ,回车即可
elasticsearch-plugin install file:\/usr/share/elasticsearch/elasticsearch-analysis-ik-7.14.0.zip

#第四步退出容器
exit

#第五步重启容器
docker restart 容器ID

 4.使用客户端查看

post _analyze

{

"analyzer": "ik_smart",

"text": "大学生自习室视频爆火鼻祖"

}

post _analyze

{

"analyzer": "ik_max_word",

"text": "大学生自习室视频爆火鼻祖"

}

5.原理

EelasticSearch使用

1. Easy-ES介绍

Easy-Es

2. 导入依赖包

  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.elasticsearch.client</groupId>
                    <artifactId>elasticsearch-rest-high-level-client</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.elasticsearch</groupId>
                    <artifactId>elasticsearch</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>cn.easy-es</groupId>
            <artifactId>easy-es-boot-starter</artifactId>
            <version>2.0.0-beta1</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.14.0</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.14.0</version>
        </dependency>

3. 在对像属性上添加注解 

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@IndexName( aliasName = "es_product")
public class EsProduct {
    //将id设置为自定义的类型
    @IndexId(type = IdType.CUSTOMIZE)
    private Integer id;
    @IndexField( fieldType= FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD,searchAnalyzer = Analyzer.IK_SMART)
    private String name;
    @IndexField( fieldType= FieldType.INTEGER)
    private Integer categoryId;
    @IndexField(fieldType= FieldType.DOUBLE)
    private BigDecimal price;
    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_SMART)
    private String brief;
    @IndexField(fieldType = FieldType.KEYWORD)
    private String img;
    @IndexField(fieldType = FieldType.TEXT,analyzer = Analyzer.IK_MAX_WORD)
    private List<String> tags;
    @IndexField(fieldType = FieldType.INTEGER)
    private Integer highOpinion;
    @IndexField(fieldType = FieldType.INTEGER)
    private Integer salesVolume;
    @IndexField(fieldType = FieldType.DATE)
    private LocalDateTime productionDate;
}

4.新建Mapper类,类似Mybatis的dao

public interface EsProductMapper extends BaseEsMapper<EsProduct> {

}

5.配置ES

# Easy-Es配置部分
easy-es:
  # 启用Easy-Es功能
  enable: true
  # 设置Elasticsearch服务器地址和端口
  address: 192.168.23.27:9200
  # 全局配置项,设置是否打印执行的DSL语句(便于调试)
  global-config:
    print-dsl: true

Elasticsearch DSL (Domain Specific Language) 是一种专门设计用来与Elasticsearch搜索引擎进行交互的查询语言。它是一种基于JSON格式的查询语法,允许用户以结构化的方式来构建复杂的查询、过滤条件、聚合操作以及其他高级功能。

通过Elasticsearch DSL,开发人员可以灵活且高效地执行各种查询操作,包括全文本搜索、精确匹配、范围查询、布尔组合查询、排序、分页、高亮显示文本、统计计算、地理位置查询以及复杂的聚合分析等。

6. 创建、删除、查询索引

select8中match的用法

package com.by;

import cn.easyes.core.biz.EsPageInfo;
import cn.easyes.core.conditions.select.LambdaEsQueryWrapper;
import cn.hutool.core.collection.CollUtil;
import com.by.dao.EsProductMapper;
import com.by.model.EsProduct;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.Operator;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@SpringBootTest
@Slf4j
class AppTests {
    @Autowired
    EsProductMapper esProductMapper;

    //创建索引
   // @Test   //当执行时,他会默认创建,执行时会报reason=index [esproduct/EBTP12JoTEGAAoZsQkmJvA] already exists异常,此时已经创建
    void testCreateIndex() {
        Boolean b = esProductMapper.createIndex();
        Assertions.assertTrue(b);
    }
    @Test
    //插入一个
    void insert(){
        //id我们定义的为Integer,而系统会为我们随机生成一个String类型的id以确保其唯一性,
        // 此时我们需要再model中使用@IndexId(type = IdType.CUSTOMIZE)
        EsProduct product = EsProduct.builder()
                .id(1)
                .brief("小米销量遥遥领先")
                .categoryId(1)
                .img("图片")
                .highOpinion(99)//好评
                .name("小米手机")
                .price(new BigDecimal(99))
                .productionDate(LocalDateTime.now())
                .salesVolume(200)
                .tags(CollUtil.newArrayList("为发烧而生"))
                .build();
        esProductMapper.insert(product);
    }
    @Test
    //批量插入
    void insert2(){
        delete();
        List<EsProduct> esProductList =new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            EsProduct esProduct = EsProduct.builder()
                    .id(i)
                    .name("小米"+i)
                    .img("图片地址"+i)
                    .brief("小米(MI)Redmi Note"+i+" 5G 120Hz OLED屏幕 骁龙4移动平台 5000mAh长续航 8GB+128GB子夜黑 小米红米")
                    .price(new BigDecimal(500.36+i))
                    .categoryId(1)
                    .highOpinion(100+i)
                    .productionDate(LocalDateTime.now())
                    .salesVolume(200+i)
                    .tags(CollUtil.newArrayList("12"+i+"高刷","舒适护眼"))
                    .build();
            esProductList.add(esProduct);
        }
        Integer batch = esProductMapper.insertBatch(esProductList);
    }
    @Test
    //批量删除
    void delete(){
        ArrayList<Integer> list = CollUtil.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer integer = esProductMapper.deleteBatchIds(list);
    }
    @Test
    void delete2(){
        LambdaEsQueryWrapper<EsProduct> esQueryWrapper = new LambdaEsQueryWrapper<>();
        LambdaEsQueryWrapper<EsProduct> wrapper = esQueryWrapper.eq(EsProduct::getId, 1);
        Integer delete = esProductMapper.delete(wrapper);
    }

    @Test
    void update(){
        LambdaEsQueryWrapper<EsProduct> esQueryWrapper = new LambdaEsQueryWrapper<>();
        LambdaEsQueryWrapper<EsProduct> wrapper = esQueryWrapper.like("name", "小");
        EsProduct product = EsProduct.builder().brief("小米为发烧而生").tags(CollUtil.newArrayList("雷总说少妇勾魂,少女勾人")).build();
        Integer update = esProductMapper.update(product, wrapper);
    }

    @Test
    void update2(){
        EsProduct product = EsProduct.builder().id(2).name("小米su7").brief("风一样的男人").build();
        Integer update = esProductMapper.updateById(product);
    }

    @Test
    void update3(){
        ArrayList<EsProduct> list = CollUtil.newArrayList();
        for (int i = 2; i < 5; i++) {
            EsProduct product = EsProduct.builder().id(i).name("新能源汽车").brief("风一样的男人").price(new BigDecimal(7888)).build();
            list.add(product);
        }
        Integer integer = esProductMapper.updateBatchByIds(list);
    }
    @Test
    void select(){
        EsProduct esProduct = esProductMapper.selectById(2);
    }

    @Test
    void select2(){
        List<EsProduct> esProductList = esProductMapper.selectBatchIds(CollUtil.newArrayList(2, 3, 4, 5));
    }
    @Test
    void select3(){
        LambdaEsQueryWrapper<EsProduct> queryWrapper = new LambdaEsQueryWrapper<>();
        queryWrapper.like("name","米");
        List<EsProduct> esProducts = esProductMapper.selectList(queryWrapper);
    }
    @Test
    void select4(){
        LambdaEsQueryWrapper<EsProduct> queryWrapper = new LambdaEsQueryWrapper<>();
        queryWrapper.eq("category",1);
        List<EsProduct> esProducts = esProductMapper.selectList(queryWrapper);
    }
    @Test
    void select5(){
        LambdaEsQueryWrapper<EsProduct> queryWrapper = new LambdaEsQueryWrapper<>();
        queryWrapper.in("id",4,5,6);
        List<EsProduct> esProducts = esProductMapper.selectList(queryWrapper);
    }
    @Test
    void select6(){
        LambdaEsQueryWrapper<EsProduct> queryWrapper = new LambdaEsQueryWrapper<>();
      //  queryWrapper.queryStringQuery("汽车之家");
        queryWrapper.queryStringQuery("汽车之家",1.0f);
        List<EsProduct> esProducts = esProductMapper.selectList(queryWrapper);
    }
    @Test
    void select7(){
        LambdaEsQueryWrapper<EsProduct> queryWrapper = new LambdaEsQueryWrapper<>();
        //  queryWrapper.queryStringQuery("汽车之家");
        queryWrapper.match(EsProduct::getName,"汽车",1.0f)
                .or()//拼接或者的意思
                .match(EsProduct::getBrief,"小米",2.0f);
        List<EsProduct> esProducts = esProductMapper.selectList(queryWrapper);
    }
    @Test
    void select8(){
        LambdaEsQueryWrapper<EsProduct> queryWrapper = new LambdaEsQueryWrapper<>();
       // queryWrapper.multiMatchQuery("汽车", Operator.AND,EsProduct::getName,EsProduct::getBrief);
      //  String name = "";
       // queryWrapper.multiMatchQuery(name==null,"小米",EsProduct::getName);
        queryWrapper.and(w->w.match(EsProduct::getName,"小米",1.0f)
                .or()
                .match(EsProduct::getBrief,"汽车",2.0f)
                .or().match(EsProduct::getTags,"发烧",3.0f));
        queryWrapper.orderByDesc(EsProduct::getSalesVolume);
        List<EsProduct> esProducts = esProductMapper.selectList(queryWrapper);
        EsPageInfo<EsProduct> pageQuery = esProductMapper.pageQuery(queryWrapper, 2, 3);

    }
    @Test
    void select9(){
        LambdaEsQueryWrapper<EsProduct> queryWrapper = new LambdaEsQueryWrapper<>();
        queryWrapper.match(EsProduct::getName,"水汽车门");
        List<EsProduct> esProductList = esProductMapper.selectList(queryWrapper);
    }
}

7. 原生Api调用

7.1查看索引mapping关系

GET /es_product/_mapping

7.2查看某个文档,具体字段的分词

GET /product/_doc/2/_termvectors?fields=brief

  • 19
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值