侧边栏壁纸
博主头像
孔子说JAVA博主等级

成功只是一只沦落在鸡窝里的鹰,成功永远属于自信且有毅力的人!

  • 累计撰写 352 篇文章
  • 累计创建 135 个标签
  • 累计收到 10 条评论

目 录CONTENT

文章目录

ES教程10-Boost加权组合查询及示例

孔子说JAVA
2022-10-15 / 0 评论 / 0 点赞 / 361 阅读 / 5,293 字 / 正在检测是否收录...
广告 广告

boost 参数被用来提升一个语句的相对权重(boost值大于 1 )或降低相对权重(boost值处于 0 到 1 之间),可以直接影响bm25的评分评分机制, 从而影响整体结果的相关度,这是一个非常好用,而且非常关键的一个参数。通过利用boost参数,可以对某个字段进行提权,在es 5.x 以后的版本中,有精确值字段(keyword)和全文搜索字段(text)。

1、boost参数语法

精确查询(提权)

{
    "query": {
        "term": {"field_a": {"value": "hello a", "boost": 2.0}
    }
}

全文搜索(降权)

{
    "query": {
        "match": {"field_b": {"query": "hello b", "boost": 0.5}
    }
}

提权和降权

GET /product_codes_reindex/_search
{
  "query": {
    "boosting": {
      # 正向加权
      "positive": {
        "term": {
          "merchantId": {
            "value": "1071168956150054913",
            "boost": 1.2
          }
        }
      },
      # 反向加权
      "negative": {
        "term": {
          "companyId": {
            "value": "1047621472136200192"
          }
        }
      },
      "negative_boost": 0.2
    }
  }
}

2、boost使用示例

我们需要查询关于 “full-text search(全文搜索)” 的文档,同时希望为提及 “Elasticsearch” 或 “Lucene” 的文档给予更高的权重 ,这里的 更高权重 是指如果文档中出现 “Elasticsearch” 或 “Lucene” 时,它们会比没有的出现这些词的文档获得更高的相关度评分 _score ,也就是说,它们会出现在结果集的更上面。

2.1 未使用boost参数

GET /_search
{
    "query": {
        "bool": {
            "must": {
                "match": {
                    "content": { 
                        "query":    "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [ 
                { "match": { "content": "Elasticsearch" }},
                { "match": { "content": "Lucene"        }}
            ]
        }
    }
}

这个语句中,should 语句匹配得越多表示文档的相关度越高:

  • content 字段必须包含 full 、 text 和 search 所有三个词。
  • should 表示如果 content 字段也包含 Elasticsearch 或 Lucene ,文档会获得更高的评分 _score 。

但是如果我们想让包含 Lucene 的有更高的权重,并且包含 Elasticsearch 的语句比 Lucene 的权重更高,该如何处理?

  • 这就需要用到boost参数。

2.2 使用boost参数

通过指定 boost 来控制任何查询语句的相对的权重, boost 的默认值为 1 ,大于 1 会提升一个语句的相对权重。我们重写下之前的查询:

GET /_search
{
    "query": {
        "bool": {
            "must": {
                "match": {  
                    "content": {
                        "query":    "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [
                { "match": {
                    "content": {
                        "query": "Elasticsearch",
                        "boost": 3 
                    }
                }},
                { "match": {
                    "content": {
                        "query": "Lucene",
                        "boost": 2 
                    }
                }}
            ]
        }
    }
}
  • 第一个match处的语句使用默认的 boost 值为 1 。
  • should中的第一个match处的语句更为重要,因为它有最高的 boost 值 3。
  • should中的第二个match处的语句比使用默认值的更重要,但它的重要性不及 Elasticsearch 语句。

3、constant_score查询

constant_score:本意(常量分数),可以将一个不变的常量应用到所有匹配的文档中。它常用于只需要执行一个filter而没有其他查询(例如评分查询)的情况下。term查询被放置在constant_score中,转换成不评分的filter。这种方式可以用来只有filter的bool查询中。

3.1 数据准备

# 创建索引
PUT test_terms
#创建映射
PUT test_terms/_mapping
{
  "properties":{
    "aid":{
      "type":"keyword",
      "index":true
    },
    "name":{
      "type":"text",
      "index":true
    },"tag":{
      "type":"keyword",
      "index":true
    }
  }
}
#查看映射
GET test_terms/_mapping

# 批量生成数据
POST _bulk
{"create":{"_index":"test_terms","_type":"_doc"}}
{"aid":"1001","name":"JAVA book","tag":["JAVA","book"]}
{"create":{"_index":"test_terms","_type":"_doc"}}
{"aid":"1002","name":"PHP dic page","tag":["PHP","page","learning"]}
{"create":{"_index":"test_terms","_type":"_doc"}}
{"aid":"1003","name":"JAVA hadoop","tag":["hadoop","JAVA"]}
{"create":{"_index":"test_terms","_type":"_doc"}}
{"aid":"1004","name":"hadoop","tag":["hadoop"]}

# 单条插入数据
POST test_terms/_doc
{
  "aid":"1005",
  "name":"JAVA ES hadoop",
  "tag":["JAVA","JAVA","ES"]
}

3.2 使用constant_score查询

GET test_terms/_search
{
  "query": {
    "bool": {
      "should": [
        {"constant_score": {
          "filter": {"term": {
            "tag": "JAVA"
          }},
          "boost": 1
        }},
        {"constant_score": {
          "filter": {"term": {
            "tag": "hadoop"
          }},
          "boost": 1
        }}
      ]
    }
  }
}

本质相当于:

GET test_terms/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "filter": {
              "term": {
                "tag": "JAVA"
              }
            }
          }
        }
      ]
    }
  }
}

只是bool中只有filter操作,故使用constant_score代替了filter操作,且为每一个子查询设置了常量分数。

image-1665541048328

由上述结果中也可以看出,_score的计算规则:每一个子查询都独自计算doc的相关性得分,一旦他们的得分被计算出来,bool查询就将这些得分进行合并并且返回一个代表整个bool操作的得分。

3.3 不使用constant_score

GET test_terms/_search
{
  "query": {
    "bool": {
      "should": [
        {"term": {
          "tag": {
            "value": "JAVA",
            "boost": 2
          }
        }},
        {
        "term": {
          "tag": {
            "value": "hadoop",
            "boost": 1
          }
        }  
        }
      ]
    }
  }
}

image-1665541098575

与使用constant_score的区别是,should参与评分计算,而我们设置的boost只是参与评分的权重比例。并不是一个具体的分数值。这也就是为何这种方式计算出来的score存在小数的原因。

4、总结

  • boost 参数被用来提升一个语句的相对权重( boost 值大于 1 )或降低相对权重( boost 值处于 0 到 1 之间),但是这种提升或降低并不是线性的,换句话说,如果一个 boost 值为 2 ,并不能获得两倍的评分 _score

  • 新的评分 _score 会在应用权重提升之后被 归一化 ,每种类型的查询都有自己的归一算法,更高的 boost 值为我们带来更高的评分 _score

  • 查询时的权重提升是可以用来影响相关度的主要工具,任意类型的查询都能接受 boost 参数。将 boost 设置为 2 ,并不代表最终的评分 _score 是原值的两倍;实际的权重值会经过归一化和一些其他内部优化过程。尽管如此,它确实想要表明一个提升值为 2 的句子的重要性是提升值为 1 语句的两倍。

  • 在实际应用中,无法通过简单的公式得出某个特定查询语句的 “正确” 权重提升值,只能通过不断尝试获得。需要记住的是 boost 只是影响相关度评分的其中一个因子;它还需要与其他因子相互竞争。所以不要想当然的去盲目提升一些字段的权重。选择权重,检查结果,如此反复。

0

评论区