• Elasticsearch 单字符串多字段查询


    前言

    有些时候,我们搜索的时候,只会提供一个输入框,但是会查询相关的多个字段,典型的如Google搜索,我们该如何用 Elasticsearch 如何实现呢?

    实例

    从单字符串查询的实例说起

    创建测试例子的数据

    DELETE blogs
    
    PUT blogs/_doc/_bulk
    {"index":{"_id":1}}
    {"title": "Quick brown rabbits","body": "Brown rabbits are commonly seen."}
    {"index":{"_id":2}}
    {"title": "Keeping pets healthy","body": "My quick brown fox eats rabbits on a regular basis"}
    
    GET blogs/_search
    {
      "explain": true,
      "query": {
        "bool": {
          "should": [
            {"match": {"title": "Brown fox"}},
            {"match": {"body": "Brown fox"}}
          ]
        }
      }
    }
    

    上面的例子相关性的值是title与body的简单相加,可以通过“"explain": true”打印出来的数据进行查询计算的过程。

    最优字段查询调优

    可以使用disjunction max query,让其匹配最大相关性那个字段,同时tie_breaker可以调整相关性,取值范围是0~1,可以控制相关性较小那个值占用的比例,默认是0,毕竟只要相关性最大那个字段就好了,其他字段不打分。

    GET blogs/_search
    {
      "explain": true,
      "query": {
        "dis_max": {
          "queries": [
            {"match": {"title": "Brown fox"}},
            {"match": {"body": "Brown fox"}}
          ],
          "tie_breaker": 0.7
        }
      }
    }
    

    相关性的值是title与body中的最大值。

    multi_match

    multi_match 查询为能在多个字段上反复执行相同查询提供了一种便捷方式。

    上面的dis_max例子改写如下

    GET blogs/_search
    {
      "explain": true, 
      "query": {
        "multi_match": {
          "type": "most_fields", 
          "query": "Brown fox",
          "fields": ["title","body"],
          "tie_breaker": 0.7
        }
      }
    }
    

    multi_match 查询

    multi_match 支持三种场景

    • best_fields——(默认)查找匹配任何字段的文档,但是使用最佳匹配字段的_score。
    • most_fields——查找匹配任何字段的文档,结合每个字段的_score。
    • cross_fields——用相同的分析器处理字段,把这些字段当作一个大字段。查找任何字段的每个单词。类似copy_to

    query中可以指定minimum_should_match、operator等字段,会把这些字段传递到query语句中

    best_fields

    当搜索词语具体概念的时候,比如 “brown fox” ,词组比各自独立的单词更有意义。像 title 和 body 这样的字段,尽管它们之间是相关的,但同时又彼此相互竞争。文档在相同字段 中包含的词越多越好,评分也来自于最匹配字段 。

    best_fields 语句 等同于 dis_max 语句,可以配置tie_breaker参数。

    most_fields

    全文搜索被称作是 召回率(Recall) 与 精确率(Precision) 的战场: 召回率 ——返回所有的相关文档; 精确率 ——不返回无关文档。目的是在结果的第一页中为用户呈现最为相关的文档。

    为了提高召回率的效果,我们扩大搜索范围——不仅返回与用户搜索词精确匹配的文档,还会返回我们认为与查询相关的所有文档。如果一个用户搜索 “quick brown box” ,一个包含词语“fast foxes”的文档被认为是非常合理的返回结果。

    提高全文相关性精度的常用方式是为同一文本建立多种方式的索引,每种方式都提供了一个不同的相关度信号signal。主字段会以尽可能多的形式的去匹配尽可能多的文档。

    DELETE titles
    
    PUT titles
    {
      "mappings": {
        "properties": {
          "title": {
            "type": "text",
            "analyzer": "english",
            "fields": {"std": {"type": "text","analyzer": "standard"}}
          }
        }
      }
    }
    
    GET /titles/_search
    {
      "query": {
        "multi_match": {
          "query":  "barking dogs",
          "type":   "most_fields",
          "fields": [ "title^10", "title.std" ]
        }
      }
    }
    

    比如这个例子,文档中的“title”被索引了两次,主字段“title”的分词器是“english”,会提取词干,“a”,“the”等这些会在分词过程中被过滤掉,“ing”等会去除,子字段“title.std”的分词器是“standard”,不会提取词干。

    同时指定了boost,比如上面的“title^10”,表示“title”的权重是10。

    cross_fields

    对于某些实体,我们需要在多个字段中确定其信息,单个字段都只能作为整体的一部分:

    Person: first_name 和 last_name (人:名和姓)
    Book: title 、 author 和 description (书:标题、作者、描述)
    Address: street 、 city 、 country 和 postcode (地址:街道、市、国家和邮政编码)
    

    在这种情况下,我们希望在任何 这些列出的字段中找到尽可能多的词,这有如在一个大字段中进行搜索,这个大字段包括了所有列出的字段。

    这个类似copy_to,copy_to需要额外的存储空间,这个不需要。

    支持 operator 操作,如果指定的是“and”,那么表示所有词都是必须的。

    参考资料

    __EOF__

     


     

    欢迎转载,但请注明出处!
    欢迎大家一起交流学习!如果有什么疑问,大家可以在评论区一起交流!
    如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是我的最大动力!

  • 相关阅读:
    艾伟:WinForm控件开发总结(三)认识WinForm控件常用的Attribute 狼人:
    break while(1)
    从“不太差”到“卓越”
    分享一种需求评审的方案
    高德地图 android api 实现自动定位
    Java Class Loader解析
    JAVA IO 设计模式彻底分析
    [latex]PGF 和 tikz中如何旋转图形的示例
    算法笔记之 并查集入门 POJ 1611
    Vector 和 ArrayList 哪一个更好? 为什么?
  • 原文地址:https://www.cnblogs.com/powercto/p/14537658.html
Copyright © 2020-2023  润新知