Elasticsearch 复合查询——多字符串多字段查询

前言

有时我们在搜索电影的时候,包含了多个条件,比如主演是周星驰,打分8分以上,上映时间是1990年~2001年的,那么Elasticsearch又该如何帮我们做查询呢?这里我们可以用 bool 查询来实现需求。这种查询将多查询组合在一起,成为用户自己想要的 bool 查询。

bool 查询

一个 bool 查询,可以包含一个或多个查询语句进行组合。

有4种参数

  • must:文档必须匹配这些条件才能被包含进来。贡献算分。
  • should:文档选择性匹配,如果满足这些语句中的任意语句,将增加 _score ,否则,无任何影响。贡献算分。
  • must_not:文档必须不匹配这些条件才能被包含进来。
  • filter:必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。不贡献算分。

基本语法

  • bool 里面的子查询继续嵌套 bool 查询
  • 子查询可以以任意顺序出现
  • 如果没有 must 语句,那么至少需要能够匹配其中的一条 should 语句。但如果存在至少一条 must 语句,则对 should 语句的匹配没有要求。
  • must等可以跟一个对象(“{}”),也可以跟数组(“[]”)
{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }}
        ],
        "filter": {
          "bool": { 
              "must": [
                  { "range": { "date": { "gte": "2014-01-01" }}},
                  { "range": { "price": { "lte": 29.99 }}}
              ],
              "must_not": [
                  { "term": { "category": "ebooks" }}
              ]
          }
        }
    }
}

一个航班查询的例子,搜索去往美国的,当地天气是晴朗的,不从日本出发的,票价小于等于1000的航班。

GET kibana_sample_data_flights/_search
{
  "size": 5,
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "DestCountry": "US"
          }
        },
        {
          "term": {
            "DestWeather": "Sunny"
          }
        }
      ],
      "must_not": {
        "term": {
            "OriginCountry": "JP"
          }
      }, 
      "filter": {
        "range": {
          "AvgTicketPrice": {
            "lte": 1000
          }
        }
      }
    }
  }
}

控制相关性

那么多个字段的查询,我们该如何影响其相关性的算分呢?

层级嵌套

同一层级下的字段是竞争关系,具有相同权重,可以通过嵌套改变对算分的影响。

GET animals/_search
{
  "query": {
    "bool": {
      "should": [
        {"term": {"text": "brown"}},
        {"term": {"text": "red"}},
        {"term": {"text": "quick"}},
        {"term": {"text": "dog"}}
      ]
    }
  }
}

GET animals/_search
{
  "query": {
    "bool": {
      "should": [
        {"term": {"text": "brown"}},
        {"term": {"text": "red"}},
        {"bool": {
            "should": [
                {"term": {"text": "quick"}},
                {"term": {"text": "dog"}}
            ]
          }
        }
      ]
    }
  }
}

boosting

控制字段的权重,可以使用boosting,默认值是1,可正可负。

  • 当boost>1时,打分的相关性相对提升
  • 当0<boost<1时,打分的相关性相对降低
  • 当boost<0时,贡献负分

精简语法,可以在match里面指定boost,比如上面的航班信息DestCountry部分字段设置权重。

GET kibana_sample_data_flights/_search
{
  "explain": true,
  "size": 5,
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "DestCountry": {
              "query": "US",
              "boost": 10
            }
          }
        },
        {
          "term": {
            "DestWeather": "Sunny"
          }
        }
      ],
      "must_not": {
        "term": {
          "OriginCountry": "JP"
        }
      },
      "filter": {
        "range": {
          "AvgTicketPrice": {
            "lte": 1000
          }
        }
      }
    }
  }
}

完整boosting语法,positive正向作用,negative负向作用,negative_boost负向作用的权重,可以用来降级匹配的文档,不像“NOT”逻辑运算直接去除相关的文档

GET movies/_search
{
  //"explain": true, 
  "query": {
    "boosting": {
      "positive": {
        "term": {
          "title": {
            "value": "beautiful"
          }
        }
      },
      "negative": {
        "term": {
          "title": {
            "value": "mind"
          }
        }
      },
      "negative_boost": 0.2
    }
  }
}

constant_score 查询

尽管没有 bool 查询使用这么频繁,constant_score 查询也是我们工具箱里有用的查询工具。它将一个不变的常量评分应用于所有匹配的文档。它被经常用于你只需要执行一个 filter 而没有其它查询(例如,评分查询)的情况下。

GET movies/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "title": "beautiful"
        }
      }
    }
  }
}

参考资料

给TA买糖
共{{data.count}}人
人已赞赏
经验教程

策略模式在PHP业务代码的实践

2021-3-14 16:23:00

经验教程

Spring Boot 自动配置 源码分析

2021-3-14 16:31:00

⚠️
免责声明:根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。 本站为个人博客非盈利性站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途,网站会员捐赠是您喜欢本站而产生的赞助支持行为,仅为维持服务器的开支与维护,全凭自愿无任何强求。本站部份代码及教程来源于互联网,仅供网友学习交流,若您喜欢本文可附上原文链接随意转载。
无意侵害您的权益,请发送邮件至 momeis6@qq.com 或点击右侧 私信:momeis 反馈,我们将尽快处理。
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索