ElasticSearch系列六:ElasticSearch搜索技术深入讲解(一)

这篇具有很好参考价值的文章主要介绍了ElasticSearch系列六:ElasticSearch搜索技术深入讲解(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.match 手工控制搜索结果精准度

GET /product_db/_search
{
  "query": {
    "match": {
      "subTitle": "白色 通版"
    }
  }
}

等价于

GET /product_db/_search
{
  "query": {
    "match": {
      "subTitle": {
        "query": "白色 通版",
        "operator": "or"
      }
    }
  }
}

如果需要收索subTitle字段中包含"白色"和"通版",需将 or 改成 and, 如下:

GET /product_db/_search
{
  "query": {
    "match": {
      "subTitle": {
        "query": "白色 通版",
        "operator": "and"
      }
    }
  }
}

        1.1. minimum_should_match 用法

GET /product_db/_search
{
  "query": {
    "match": {
      "subTitle": {
        "query": "白 通 家",
        "minimum_should_match": "67%"
      }
    }
  }
}

等价于

GET /product_db/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "subTitle": "白"
          }
        },
        {
          "match": {
            "subTitle": "通"
          }
        },
        {
          "match": {
            "subTitle": "家"
          }
        }
      ],
      "minimum_should_match": 2
    }
  }
}

        1.2 match底层转换

        在ES中,执行match搜索的时候,ES底层通常都会对搜索条件进行底层转换,来实现最终的搜索结果。如

        1.2.1(bool + should)

GET /es_db/_search
{
  "query": {
    "match": {
      "remark": "java developer"
    }
  }
}

转换后是:

GET /es_db/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "remark": "java"
          }
        },
        {
          "match": {
            "remark": "developer"
          }
        }
      ]
    }
  }
}

         1.2.2(bool + must)

GET /product_db/_search
{
  "query": {
    "match": {
      "subTitle": {
        "query": "白 通",
        "operator": "and"
      }
    }
  }
}

转换后:

GET /product_db/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "subTitle": "白"
          }
        },
        {
          "term": {
            "subTitle": "通"
          }
        }
      ]
    }
  }
}

建议:如果不怕麻烦,尽量使用转换后的语法执行搜索,效率更高。如果开发周期短,工作量大,使用简化的写法。

2. boost权重控制

        搜索document中remark字段中包含java的数据,如果remark中包含developer或architect,则包含architect的document优先显示。(就是将architect数据匹配时的相关度分数增加)。一般用于搜索时相关度排序使用。如:电商中的综合排序。将一个商品的销量,广告投放,评价值,库存,单价比较综合排序。在上述的排序元素中,广告投放权重最高,库存权重最低。

GET /es_db/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "remark": "java"
          }
        }
      ],
      "should": [
        {
          "match": {
            "remark": {
              "query": "developer",
              "boost": 1
            }
          }
        },
        {
          "match": {
            "remark": {
              "query": "architect",
              "boost": 3
            }
          }
        }
      ]
    }
  }
}

3. 基于dis_max实现best fields策略进行多字段搜索

        best fields策略: 搜索的document中的某一个field,尽可能多的匹配搜索条件。与之相反的是,尽可能多的字段匹配到搜索条件(most fields策略)。如百度搜索使用这种策略。

        优点:精确匹配的数据可以尽可能的排列在最前端,且可以通过minimum_should_match来去除长尾数据,避免长尾数据字段对排序结果的影响。什么时长尾数据呢,比如说我们搜索4个关键词,但很多文档只匹配1个,也显示出来了,这些文档其实不是我们想要的。

        缺点:相对排序不均匀。

        dis_max语法: 直接获取搜索的多条件中的,单条件query相关度分数最高的数据,以这个数据做相关度排序。

        下述的案例中,就是找name字段中"小米"匹配相关度分数或keywords字段中"手机"匹配相关度分数,哪个高,就使用哪一个相关度分数进行结果排序

GET /product_db/_search
{
  "query": {
    "dis_max": {
      "tie_breaker": 0.7,
      "boost": 1.2,
      "queries": [
        {
          "match": {
            "name": "小米"
          }
        },
        {
          "match": {
            "keywords": "手机"
          }
        }
      ]
    }
  }
}

        dis_max是将多个搜索query条件中相关度分数最高的用于结果排序,忽略其他query分数,在需要其他query条件中的相关度介入最终的结果排序,这个时候可以使用tie_breaker参数来优化dis_max搜索。tie_breaker参数代表的含义是:将其他query搜索条件的相关度分数乘以参数值,再参与到结果排序中。如果不定义此参数,相当于参数值为0。所以其他query条件的相关度分数被忽略。

4. 使用 multi_match 简化 dis_max + tie_breaker

GET /es_db/_search
{
  "query": {
    "dis_max": {
      "queries": [
        {
          "match": {
            "name": "rod"
          }
        },
        {
          "match": {
            "remark": {
              "query": "java developer",
              "boost": 2,
              "minimum_should_match": 2
            }
          }
        }
      ],
      "tie_breaker": 0.5
    }
  }
}

#使用multi_match语法为:其中type常用的有best_fields和most_fields。^n代表权重,相当于"boost":n。

GET /es_db/_search
{
  "query": {
    "multi_match": {
      "query": "rod java developer",
      "fields": [
        "name",
        "remark^2"
      ],
      "type": "best_fields",
      "tie_breaker": 0.5,
      "minimum_should_match": "50%"
    }
  }
}

5. cross fields搜索

        Cross fields : 一个唯一的标识,分部在多个fields中,使用这种唯一标识搜索数据就称为cross fields搜索。如:人名可以分为姓和名,地址可以分为省、市、区县、街道等。那么使用人名或地址来搜索document,就称为cross fields搜索。实现这种搜索,一般都是使用most fields搜索策略。因为这就不是一个field的问题。

        Cross fields搜索策略,是从多个字段中搜索条件数据。默认情况下,和most fields搜索的逻辑是一致的,计算相关度分数是和best fields策略一致的。一般来说,如果使用cross fields搜索策略,那么都会携带一个额外的参数operator。用来标记搜索条件如何在多个字段中匹配。在ES中也有cross fields搜索策略。具体语法如下:

GET /es_db/_search
{
  "query": {
    "multi_match": {
      "query": "java developer",
      "fields": [
        "name",
        "remark"
      ],
      "type": "cross_fields",
      "operator": "and"
    }
  }
}

        上述语法代表的是,搜索条件中的java必须在name或remark字段中匹配,developer也必须在name或remark字段中匹配。

        most field策略问题:most fields策略是尽可能匹配更多的字段,所以会导致精确搜索结果排序问题。又因为cross fields搜索,不能使用minimum_should_match来去除长尾数据。所以在使用most fields和cross fields策略搜索数据的时候,都有不同的缺陷。所以商业项目开发中,都推荐使用best fields策略实现搜索。

6. copy_to组合fields

        如果在搜索框中输入“手机”,点击搜索,那么是在商品的类型名称、商品的名称、商品的卖点、商品的描述等字段中,哪一个字段内进行数据的匹配?如果使用某一个字段做搜索不合适,那么使用_all做搜索是否合适?也不合适,因为_all字段中可能包含图片,价格等字段。假设,有一个字段,其中的内容包括(但不限于):商品类型名称、商品名称、商品卖点等字段的数据内容。是否可以在这个特殊的字段上进行数据搜索匹配?

        copy_to : 就是将多个字段,复制到一个字段中,实现一个多字段组合。copy_to可以解决cross fields搜索问题,在商业项目中,也用于解决搜索条件默认字段问题。使用copy_to语法时,需要在定义index的时候,手工指定mapping映射策略。

copy_to语法:

PUT /es_db/_mapping
{
  "properties": {
    "provice": {
      "type": "text",
      "analyzer": "standard",
      "copy_to": "address"
    },
    "city": {
      "type": "text",
      "analyzer": "standard",
      "copy_to": "address"
    },
    "street": {
      "type": "text",
      "analyzer": "standard",
      "copy_to": "address"
    },
    "address": {
      "type": "text",
      "analyzer": "standard"
    }
  }
}

        上述的mapping定义中,是新增了4个字段,分别是provice、city、street、address,其中provice、city、street三个字段的值,会自动复制到address字段中,实现一个字段的组合。那么在搜索地址的时候,就可以在address字段中做条件匹配,从而避免most fields策略导致的问题。在维护数据的时候,不需对address字段特殊的维护。因为address字段是一个组合字段,是由ES自动维护的。类似java代码中的推导属性。在存储的时候,未必存在,但是在逻辑上是一定存在的,因为address是由3个物理存在的属性province、city、street组成的。

7. match phrase 深入详解

        短语搜索。就是搜索条件不分词。代表搜索条件不可分割。如果hello world是一个不可分割的短语,我们可以使用前文学过的短语搜索match phrase来实现。语法如下:

GET /index/_search
{
  "query": {
    "match_phrase": {
      "remark": "java assistant"
    }
  }
}

        1)match phrase原理 -- term position

        ES是如何实现match phrase短语搜索的?其实在ES中,使用match phrase做搜索的时候,也是和match类似,首先对搜索条件进行分词-analyze。将搜索条件拆分成hello和world。既然是分词后再搜索,ES是如何实现短语搜索的?这里涉及到了倒排索引的建立过程。在倒排索引建立的时候,ES会先对document数据进行分词,如:

GET _analyze
{
  "text": "hello world, java spark",
  "analyzer": "standard"
}

结果是:

{
  "tokens" : [
    {
      "token" : "hello",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "world",
      "start_offset" : 6,
      "end_offset" : 11,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "java",
      "start_offset" : 13,
      "end_offset" : 17,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "spark",
      "start_offset" : 18,
      "end_offset" : 23,
      "type" : "<ALPHANUM>",
      "position" : 3
    }
  ]
}

        从上述结果中,可以看到。ES在做分词的时候,除了将数据切分外,还会保留一个position。position代表的是这个词在整个数据中的下标。当ES执行match phrase搜索的时候,首先将搜索条件hello world分词为hello和world。然后在倒排索引中检索数据,如果hello和world都在某个document的某个field出现时,那么检查这两个匹配到的单词的position是否是连续的,如果是连续的,代表匹配成功,如果是不连续的,则匹配失败。

        2)match phrase搜索参数 -- slop

        搜索时,如果搜索参数是hello spark。而ES中存储的数据是hello world, java spark。那么使用match phrase则无法搜索到。在这个时候,可以使用match来解决这个问题。但是,当我们需要在搜索的结果中,做一个特殊的要求:hello和spark两个单词距离越近,document在结果集合中排序越靠前,这个时候再使用match则未必能得到想要的结果。

        ES的搜索中,对match phrase提供了参数slop。slop代表match phrase短语搜索的时候,单词最多移动多少次,可以实现数据匹配。在所有匹配结果中,多个单词距离越近,相关度评分越高,排序越靠前。使用slop参数的match phrase搜索,就称为近似匹配(proximity search)

如:

        数据为: hello world, java spark

        搜索为: match phrase : hello spark。

        slop为: 3  (代表单词最多移动3次。)

执行短语搜索的时候,将条件hello spark分词为hello和spark两个单词。并且连续。

        hello   spark

        接下来,可以根据slop参数执行单词的移动。

        下标 : 0 1 2 3

        doc  : hello world java spark

        搜索 : hello  spark

        移动1: hello         spark

        移动2: hello                 spark

匹配成功,不需要移动第三次即可匹配。

        如果当slop移动次数使用完毕,还没有匹配成功,则无搜索结果。如果使用中文分词,则移动次数更加复杂,因为中文词语有重叠情况,很难计算具体次数,需要多次尝试才行。

代码示例:


GET _analyze
{
  "text": "hello world, java spark",
  "analyzer": "standard"
}

POST /test_a/_doc/3
{
  "f": "hello world, java spark"
}

GET /test_a/_search
{
  "query": {
    "match_phrase": {
      "f": {
        "query": "hello spark",
        "slop": 2
      }
    }
  }
}

GET /test_a/_search
{
  "query": {
    "match_phrase": {
      "f": {
        "query": "spark hello",
        "slop": 4
      }
    }
  }
}

8. 使用match和proximity search实现召回率和精准度平衡。

        1)召回率:召回率就是搜索结果比率,如:索引A中有100个document,搜索时返回多少个document,就是召回率(recall)。

        2)精准度:就是搜索结果的准确率,如:搜索条件为hello java,在搜索结果中尽可能让短语匹配和hello java离的近的结果排序靠前,就是精准度(precision)。

        如果在搜索的时候,只使用match phrase语法,会导致召回率底下,因为搜索结果中必须包含短语(包括proximity search);只使用match语法,会导致精准度底下,因为搜索结果排序是根据相关度分数算法计算得到。如果需要在结果中兼顾召回率和精准度的时候,就需要将match和proximity search混合使用,来得到搜索结果。

测试案例:

POST /test_a/_doc/3
{
  "f": "hello, java is very good, spark is also very good"
}

POST /test_a/_doc/4
{
  "f": "java and spark, development language "
}

POST /test_a/_doc/5
{
  "f": "Java Spark is a fast and general-purpose cluster computing system. It provides high-level APIs in Java, Scala, Python and R, and an optimized engine that supports general execution graphs."
}

POST /test_a/_doc/6
{
  "f": "java spark and, development language "
}

GET /test_a/_search
{
  "query": {
    "match": {
      "f": "java spark"
    }
  }
}

GET /test_a/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "f": "java spark"
          }
        }
      ],
      "should": [
        {
          "match_phrase": {
            "f": {
              "query": "java spark",
              "slop": 50
            }
          }
        }
      ]
    }
  }
}

 9. 前缀搜索 prefix search

        使用前缀匹配实现搜索能力。通常针对keyword类型字段,也就是不分词的字段。

  语法:

GET /test_a/_search
{
  "query": {
    "prefix": {
      "f.keyword": {
        "value": "J"
      }
    }
  }
}

注意:针对前缀搜索,是对keyword类型字段而言。而keyword类型字段数据大小写敏感

        前缀搜索效率比较低。前缀搜索不会计算相关度分数。前缀越短,效率越低。如果使用前缀搜索,建议使用长前缀。因为前缀搜索需要扫描完整的索引内容,所以前缀越长,相对效率越高。

10. 通配符搜索(需扫描完整的索引,性能低,不推荐使用)

        ES中也有通配符。但是和java还有数据库不太一样。通配符可以在倒排索引中使用,也可以在keyword类型字段中使用。

        常用通配符:

                ?  :    一个任意字符

                *  :    0~n个任意字符

GET /test_a/_search
{
  "query": {
    "wildcard": {
      "f.keyword": {
        "value": "?e*o*"
      }
    }
  }
}

 11. 正则搜索(需扫描完整的索引,性能低,不推荐使用)

        ES支持正则表达式。可以在倒排索引或keyword类型字段中使用。

        常用符号:

                []  : 范围,如: [0-9]是0~9的范围数字

                .   :  一个字符

                +  : 前面的表达式可以出现多次。

GET /test_a/_search
{
  "query": {
    "regexp": {
      "f.keyword": "[A-z].+"
    }
  }
}

12. 搜索推荐(效率低)

        搜索推荐: search as your type, 搜索提示。如:索引中有若干数据以“hello”开头,那么在输入hello的时候,推荐相关信息。(类似百度输入框)

语法:

GET /test_a/_search
{
  "query": {
    "match_phrase_prefix": {
      "f": {
        "query": "java s",
        "slop": 10,
        "max_expansions": 10
      }
    }
  }
}

        其原理和match phrase类似,是先使用match匹配term数据(java),然后在指定的slop移动次数范围内,前缀匹配(s),max_expansions是用于指定prefix最多匹配多少个term(单词),超过这个数量就不再匹配了。

        这种语法的限制是,只有最后一个term会执行前缀搜索。

        执行性能很差,毕竟最后一个term是需要扫描所有符合slop要求的倒排索引的term。

        因为效率较低,如果必须使用,则一定要使用参数max_expansions。

13. fuzzy模糊搜索技术

        搜索的时候,可能搜索条件文本输入错误,如:hello world -> hello word。这种拼写错误还是很常见的。fuzzy技术就是用于解决错误拼写的(在英文中很有效,在中文中几乎无效。)。其中fuzziness代表value的值word可以修改多少个字母来进行拼写错误的纠正(修改字母的数量包含字母变更,增加或减少字母。)。f代表要搜索的字段名称。文章来源地址https://www.toymoban.com/news/detail-611925.html

GET /test_a/_search
{
  "query": {
    "fuzzy": {
      "f": {
        "value": "word",
        "fuzziness": 2
      }
    }
  }
}

到了这里,关于ElasticSearch系列六:ElasticSearch搜索技术深入讲解(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • ElasticSearch搜索详细讲解与操作

    流程: 创建索引: 查询索引: 索引库 索引库就是存储索引的保存在磁盘上的一系列的文件。里面存储了建立好的索引消息以及文档对象。 ** 一个索引库相当于数据库中的一张表,一个文档对象相当于数据库中的一行数据 doucument对象 获取原始内容的目的是为了索引,在索引

    2024年02月16日
    浏览(24)
  • 【ElasticSearch】深入了解 ElasticSearch:开源搜索引擎的力量

    在信息时代,数据的增长速度之快让我们迅速感受到了信息爆炸的挑战。在这个背景下,搜索引擎成为了我们处理海量数据的得力工具之一。而 ElasticSearch 作为一款强大的开源搜索引擎,不仅能够高效地存储和检索数据,还在日志分析、实时监控等领域展现了其卓越的性能。

    2024年02月08日
    浏览(45)
  • ElasticSearch(四)深入搜索查询

    搜索的相关性算分,描述了一个文档和查询语句匹配成都;es 会对每个匹配条件的结果进行算分,打分的本质是排序;5之前采用TF-IDF,后面采用BM 25; (*注意:往往分词器分词的结果也会对得分产生影响,可以先看看分词的结果再去判断评分) TF-IDF 是一种用于信息检索与数

    2024年01月20日
    浏览(40)
  • 【Elasticsearch专栏 03】深入探索:Elasticsearch的倒排索引是如何提高搜索效率的?

    倒排索引之所以能够提高搜索效率,关键在于其独特的构建方式和数据结构设计。下面,我将对倒排索引的工作原理进行深层解读,并阐述其如何显著提高搜索效率。 分词与索引构建 首先,搜索引擎会对文档内容进行分词处理,将文本拆分成独立的单词或词组。然后,为每

    2024年02月22日
    浏览(29)
  • 使用阿里云试用Elasticsearch学习:2.1 深入搜索——结构化搜索

    结构化搜索(Structured search) 是指有关探询那些具有内在结构数据的过程。比如日期、时间和数字都是结构化的:它们有精确的格式,我们可以对这些格式进行逻辑操作。比较常见的操作包括比较数字或时间的范围,或判定两个值的大小。 文本也可以是结构化的。如彩色笔可

    2024年04月11日
    浏览(34)
  • 解密Elasticsearch:深入探究这款搜索和分析引擎

    作者:京东保险 管顺利 最近使用Elasticsearch实现画像系统,实现的dmp的数据中台能力。同时调研了竞品的架构选型。以及重温了redis原理等。特此做一次es的总结和回顾。网上没看到有人用Elasticsearch来完成画像的。我来做第一次尝试。 背景说完,我们先思考一件事,使用内存

    2024年02月03日
    浏览(27)
  • 一起学Elasticsearch系列-模糊搜索

    本文已收录至Github,推荐阅读 👉 Java随想录 微信公众号:Java随想录 在 Elasticsearch 中,模糊搜索是一种近似匹配的搜索方式。它允许找到与搜索词项相似但不完全相等的文档。 前缀匹配通过指定一个前缀值,搜索并匹配索引中指定字段的文档,找出那些以该前缀开头的结果

    2024年02月01日
    浏览(29)
  • 深入了解Elasticsearch搜索引擎篇:倒排索引、架构设计与优化策略

    倒排索引是一种用于快速检索的数据结构,常用于搜索引擎和数据库中。与传统的正排索引不同,倒排索引是根据来建立索引,而不是根据文档ID。 倒排索引的建立过程如下:首先,将每个文档拆分成一系列的或词项,然后建立一个词项到文档的映射。对每个关

    2024年02月12日
    浏览(41)
  • Spring Clould 搜索技术 - elasticsearch

      视频地址:微服务(SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式)  1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容 例如: 在GitHub搜索代码     在电商网站搜索商品     在百度搜索答案  

    2024年02月05日
    浏览(33)
  • 架构师系列-搜索引擎ElasticSearch(一)

    wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.5- linux-x86_64.tar.gz tar -zvxf elasticsearch-7.17.5-linux-x86_64.tar.gz 关闭防火墙 配置elasticsearch.yml   修改Linux句柄数   关闭swap 因为ES的数据大量都是常驻内存的,一旦使用了虚拟内存就会导致查询速度下降,一般需要关闭 swap,

    2024年04月14日
    浏览(34)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包