• 入门ElasticSearch :为什么选择ES作为搜索引擎?


    介绍

    随着数据量的不断增长,搜索和分析大规模数据集变得越来越重要。传统数据库在面对这种需求时往往表现不佳,这时候就需要一种专门用于搜索和分析的引擎。ElasticSearch (简称ES)就是这样一款强大的搜索引擎,它具有许多优势,使得它成为许多企业和开发者的首选。

    简单的说:ElasticSearch 是一个实时分布式存储搜索分析的引擎

    在我看来ES最强的其实是它的模糊搜索功能。
    那有的人就会问了:我数据库一样可以实现模糊搜索啊?

    select * from student where name like '%宁正%'
    
    • 1

    例如这个sql就可以查出姓名中带有宁正两字的学生
    的确,这这样做是可以模糊搜索的,但是name like '%宁正%'这种写法它是不走索引的,所以就意味着:如果你的数据量很大比如上千万,上亿条,那你不管如果去优化代码,你的查询也肯定是秒级的

    并且还有一个情况,我们大部分搜索的时候,输入的信息其实并不是很准确,例如我想搜索ElasticSearch 有关的信息,但我一不小心打成了ElesticSearch ,如果按sql语句去进行模糊搜索你就无法找到和es有关的信息

    所以在这种情况就可以使用ElasticSearch ,它就是为了搜索而生的。

    因此,我这边就把es的优点罗列出来,并进行浅显的分析:

    ES对于全文的模糊搜索非常擅长

    原因:ES是基于倒排索引,使得ES能够快速匹配关键字并返回相关结果,而不需要像传统数据库那样进行全表扫描。倒排索引在存储和查询大规模文本数据时具有较高的效率。

    那有些小伙伴看了可能就会问了:倒排索引是什么?倒排索引和正排索引有什么区别?我们日常使用的数据库可以使用倒排索引吗?

    那接下来就一个一个回答:

    倒排索引是什么?

    倒排索引是一种基于关键词的索引结构,常用于全文搜索引擎和信息检索系统中。它是一种将文档中的关键词映射到对应的文档ID的数据结构。

    具体来说,倒排索引将文档中的每个关键词与包含该关键词的文档ID建立映射。对于每个关键词,倒排索引记录了出现该关键词的文档列表,包括它们的词频、位置等信息。这使得在给定关键词的情况下,可以快速找到包含该关键词的相关文档。

    倒排索引和正排索引有什么区别?

    正排索引是一种文档ID进行排序的索引结构,它存储了文档和文档中的每个词条的详细信息。

    我有一个通俗易懂的方法来表达:

    正排索引就想我们看书时的目录,可以直接通过页码找到对应页码的内容

    而倒排索引就是将整本书中的词汇提取出来,并记录改词汇存在于哪些页码中,形成映射关系,当我想要查找一个词汇出现在哪些页中时,便只要根据这个映射表就可以快速找到想要的页数

    这么一解释,大家应该就清楚了。

    我们日常使用的数据库可以使用倒排索引吗?

    实际上,数据库是可以支持倒排索引的,但是与传统的正排索引相比,数据库倒排索引的实现相对有些复杂,而且数据库的主要设计目标是支持高效的数据管理和事务处理,而不是专注于全文搜索等复杂的查询需求

    ES的查询语法更灵活,可以精确控制查询条件和权重,以及进行更复杂的模糊搜索

    Elasticsearch的查询语法相当灵活,可以根据需要控制查询条件和权重,以及执行诸如布尔查询、范围查询、模糊查询,地理位置等复杂查询。通过使用查询语法,可以实现更精确的搜索。

    我这边写一个基于自身地理位置查询的一个demo

    geoDistanceQuery是一种地理位置查询,用于查询距离某个地理坐标点一定距离范围内的文档。只需要提供一个地理点的经纬度坐标和一个距离,以及一个单位:

    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    GeoDistanceQueryBuilder geoQuery = QueryBuilders.geoDistanceQuery("local")
                    .point(lat, lon) // 地理位置坐标
                    .distance(distance, DistanceUnit.KILOMETERS); // 查询距离
    
    sourceBuilder.query(geoQuery);
    SearchRequest searchRequest = new SearchRequest("indexName");
    searchRequest.source(sourceBuilder);
    
    // 执行查询
    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在上面的demo中,我们创建了一个geoDistanceQuery来查询location字段在给定地理位置坐标的一定距离范围内的文档。这里使用的是公里作为单位。

    ES提供了丰富的聚合和分析功能

    ES原生的提供了丰富的聚合和分析功能,可以对结果进行聚合分组排序等多种操作,并且ES还提供了许多其他的分析功能,如词频统计日期直方图等。这些功能可以帮助用户更深入地理解数据,生成仪表板和可视化图表。

    我在这边也写一个较为简单的demo,看一看就好,详细的之后的博客会讲解

    假设我们有一个索引存储了电影信息,包含字段:title(电影标题)、genre(电影类型)和rating(电影评分)。
    现在,我们希望对不同类型的电影进行聚合,并计算每个类型的平均评分。
    首先,我们需要构建一个聚合查询,指定按genre字段进行分组,并计算每个分组的平均值。

    GET movies/_search
    {
      "size": 0,
      //指定聚合操作的容器
      "aggs": { 
      	//聚合操作起的一个名字
        "genres": { 
          //指定分组字段的聚合操作类型
          "terms": { 
          	// 指定要分组的字段
            "field": "genre"
          },
          "aggs": {
          	//平均值聚合操作起的一个名字
            "avg_rating": {
              //计算均值的聚合操作类型
              "avg": {
                //操作的字段
                "field": "rating"
              }
            }
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在上面的查询中,我们使用terms聚合将电影按照genre字段进行分组,并使用avg聚合计算每个分组的rating字段的平均值。
    就会得到以下类似的结果:

    "aggregations" : {
      "genres" : {
        "buckets" : [
          {
            "key" : "Action",
            "doc_count" : 100,
            "avg_rating" : {
              "value" : 4.2
            }
          },
          {
            "key" : "Drama",
            "doc_count" : 80,
            "avg_rating" : {
              "value" : 3.8
            }
          },
          ...
        ]
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Action类的电影有100部平均评分4.2, Drama类的电影有80部平均评分3.8

    这只是聚合和分析功能的一个简单示例,实际上ES提供了更多丰富的聚合操作和分析功能,可以根据具体需求进行更复杂的操作

    ES使用分布式架构,能够更好地处理大规模数据和高并发查询

    ES分布式架构在水平扩展上的表现出色,通过将数据分片存储在多个节点上,ES可以处理大规模数据,并且能够通过并行化查询和分布式计算来提高查询性能。

    这个在这就不细讲了,之后具体介绍的是会讲述。

    那我们是无脑上ES吗,还是说要在一个特定的情况下呢?

    第一个问题的回答,显而易见的当然是不能无脑上ES!

    1. ES虽然功能强大,但也很复杂。使用它需要一定的学习和理解。如果没有适当的培训或经验,可能会遇到配置错误、性能问题、索引和查询错误等
    2. ES是一个分布式系统,需要适当的硬件和资源支持才能正常运行。如果部署不当就会导致性能问题或资源浪费。
    3. ES需要进行适当的管理和维护,包括监控集群健康状况、备份和恢复数据、更新和升级等。如果没有正确进行管理和维护,可能会遇到数据丢失、性能下降或安全风险
    4. 成本!成本!还是成本!

    第二个问题,那我们什么时候才要用ES呢?

    在我看来可以从以下几个方法来考虑:

    1. 数据规模,如果你要处理的数据高到百万甚至上亿,那你完全可以使用ES来处理大量的数据集
    2. 搜索复杂度,如果你需要经常的对全文数据进行复杂的文本查询和顾虑,那ES是一个比较好的选择
    3. 实时性,如果你需要快速地分析实时数据,那ES是一个合适的选择,它支持实时数据索引和查询,可以在数据到达时即时进行分析和可视化
    4. 分布式和高可用性需求,如果你需要一个可扩展的,具有高可用性和容错性的数据存储和分析解决方案,那ES是一个合适的选择

    所以不要因为这个技术比较厉害就无脑的去使用该技术,在使用技术的时候也要考虑到它所带来的风险

  • 相关阅读:
    系统集成|第二十一章(笔记)
    C++对象拷贝
    刷新页面,时间展示错误
    代码随想录算法训练营第四十九天|139.单词拆分
    十年架构五年生活-05第一次出差
    elementui 列表页进入详情再返回分页被重置
    Spring BeanFactory支持的Bean生命周期接口和整套初始化方法顺序
    【Spring】SpringBoot的扩展点之ApplicationContextInitializer
    技术分享 | 需要小心配置的 gtid_mode
    .NET性能优化-使用SourceGenerator-Logger记录日志
  • 原文地址:https://blog.csdn.net/qq_43649799/article/details/132637341